Click here to Skip to main content
6,595,444 members and growing! (16,935 online)
Email Password   helpLost your password?
Languages » C / C++ Language » General     Intermediate

C++ Object Introspection – (Enumerating Class Attributes)

By strtdusty

Enumerating class attributes in C++.
VC6Win2K, WinXP, MFC, Dev
Posted:14 Nov 2002
Views:40,704
Bookmarked:15 times
Announcements
Loading...
 
Search    
Advanced Search
Add to IE Search
printPrint   add Share
      Discuss Discuss   Broken Article?Report  
6 votes for this article.
Popularity: 2.18 Rating: 2.80 out of 5
1 vote, 33.3%
1
1 vote, 33.3%
2

3

4
1 vote, 33.3%
5

Introduction

You've probably worked with programming languages that allowed you to inspect an object to determine what attributes make up the object at runtime (FoxPro, Perl etc). This feature is very handy if you need to write generic serialization routines. If you are programming in C++ then you probably also know that this type of introspection is missing.

Using the code

I've tried to create a series of macros and classes which will allow you to expose the attributes of your classes at runtime, with little change to your existing code. To accomplish this, all you need to do is inherit your class from CExposeAttributes and in the constructor of your class add one line for every attribute. Of course, I am making a big assumption. The assumption is that you have implemented Get/Set methods for all of your attributes. CExposeAttributes works by maintaining a list of function pointers to those Get/Set methods. This exposes the class' attributes, but only through the public methods. In addition, I have only implemented support for the following data types: long, double, CString, CGuid, bool and LPCTSTR. The Get/Set methods must conform to the following function signatures:

//

    long:
        YourSetFunction(long l);
        long YourGetFunction() const;
    double:
        YourSetFunction(double l);
        double YourGetFunction() const;
    bool:
        YourSetFunction(bool l);
        bool YourGetFunction() const;
    LPCTSTR:
        YourSetFunction(LPCTSTR l);
        LPCTSTR YourGetFunction() const;
    CString:
        YourSetFunction(const CString& l);
        CString YourGetFunction() const;
    CGuid:
        YourSetFunction(const CGuid& l);
        CGuid YourGetFunction() const;

If you adhere to some other standard of Get/Set methods, you will need to modify or add support for the function pointer typedef's in CGetAttribute and CSetAttribute. Instructions are in the code (serialize.h) for adding support for additional data types.

//

//SAMPLE Class



class CSampleAttribute : public CXMLSerialization,
                 CExposeAttributes<csampleattribute>
{
public:
    CSampleAttribute();
    virtual ~CSampleAttribute();

    void SetName(LPCTSTR sName){m_sName=sName;};
    LPCTSTR GetName() const {return m_sName;};

    void SetSize(double dSize){m_dSize=dSize;};
    double GetSize() const {return m_dSize;};

    void SetLength(long lLength){m_lLength=lLength;};
    long GetLength() const {return m_lLength;};

    void SetID(const CGuid& oID){m_ID=oID;};
    CGuid GetID() const {return m_ID;};

    bool Save(MSXML2::IXMLDOMElementPtr& pParentElement);
    bool Load(MSXML2::IXMLDOMElementPtr& pElement,const CGuid& oID);

private:
    CString m_sName;
    double m_dSize;
    long m_lLength;
    CGuid m_ID;
};
</csampleattribute>

Assuming you have your Get/Set methods defined, you are ready to declare the attributes. To do this, in your class' constructor use one of the following macros:

//

CSampleAttribute::CSampleAttribute()
{
    //Declare all of the attributes by identifying 

    //a name and the corresponding Set/Get methods

    SET_CGUID_ATTRIBUTE(CSampleAttribute,"ID",SetID,GetID);
    SET_LPCTSTR_ATTRIBUTE(CSampleAttribute,"Name",SetName,GetName);
    SET_LONG_ATTRIBUTE(CSampleAttribute,"Length",SetLength,GetLength);
    SET_DOUBLE_ATTRIBUTE(CSampleAttribute,"Size",SetSize,GetSize);
}

That's it! Your class now has a couple of methods that will allow you to enumerate all of it's attributes. Calling GetGetAttributes or GetSetAttributes will return you a list of CGetAttribute or CSetAttribute. You can write serialization classes that can enumerate through any object and read/write its attributes. I have included a sample class called CXMLSerialization. If you inherit your class from CXMLSerialization then you will inherit two methods:

virtual bool Save(MSXML2::IXMLDOMElementPtr& pParentElement) =0;
virtual bool Load(MSXML2::IXMLDOMElementPtr& pElement, const CGuid& oID) =0;

Override these methods to allow your class to write its attributes to an XML element.

//

bool CSampleAttribute::Save(MSXML2::IXMLDOMElementPtr& pParentElement)
{
    //Override the save method of CXMLSerialization

    ASSERT(pParentElement!=NULL);

    //Don't save if we don't need to

    if (GetDirty()== false)
        return true;

    CString sXPATH;
    CXMLAttribute<csampleattribute> oAttribute;

    //Find the correct element (if it exists)

    sXPATH.Format("%s[@%s='%s']","SampleAttribute", 
                          "ID",GetID().CStrValUCase());
    MSXML2::IXMLDOMElementPtr pCur = 
        pParentElement->selectSingleNode((LPCTSTR)sXPATH);
    if (pCur == NULL)
    {
      //It didn't exists, create the element

      pCur = 
       pParentElement->GetownerDocument()->createElement("SampleAttribute");
      pParentElement->appendChild(pCur);
    }

    oAttribute.Save(pCur,this,this);
    SetDirty(false);
    return true;
}
bool CSampleAttribute::Load
   (MSXML2::IXMLDOMElementPtr& pElement,const CGuid& oID)
{
    ASSERT(pElement!=NULL);
    CXMLAttribute<csampleattribute> oAttribute;

    oAttribute.Load(pElement,this,this);
    SetDirty(false);
    return true;
}
</csampleattribute></csampleattribute>

CXMLAttribute knows how to load and save all types of attributes to and from XML. A similar class could easily be created to read/write to a relational database.

License

This article has no explicit license attached to it but may contain usage terms in the article text or the download files themselves. If in doubt please contact the author via the discussion board below.

A list of licenses authors might use can be found here

About the Author

strtdusty


Member

Occupation: Web Developer
Location: United States United States

Other popular C / C++ Language articles:

Article Top
You must Sign In to use this message board.
FAQ FAQ 
 
Noise Tolerance  Layout  Per page   
 Msgs 1 to 3 of 3 (Total in Forum: 3) (Refresh)FirstPrevNext
GeneralUmm... PinmemberTodd C. Wilson11:45 16 Nov '02  
GeneralCool PinsussAnonymous1:04 16 Nov '02  
GeneralCGuid PinsussTyler Edwards13:43 15 Nov '02  

General General    News News    Question Question    Answer Answer    Joke Joke    Rant Rant    Admin Admin   

PermaLink | Privacy | Terms of Use
Last Updated: 14 Nov 2002
Editor: Smitha Vijayan
Copyright 2002 by strtdusty
Everything else Copyright © CodeProject, 1999-2009
Web18 | Advertise on the Code Project