Thread: Is there an equivalent of the C offsetof macro for non "POD" classes ?

  1. #1
    [](){}(); manasij7479's Avatar
    Join Date
    Feb 2011
    Location
    *nullptr
    Posts
    2,657

    Is there an equivalent of the C offsetof macro for non "POD" classes ?

    Perhaps, why I need it would be more enlightening .

    I have a class called token. A class called Literal is derived from it.

    Now, look at the following code:
    Code:
    token* t = token_factory("7479");  //token_factory() returns a pointer to a Literal(or other subclasses as appropriate from the argument) allocated and constructed.
    
    cout<< t->num;
     //Literals are supposed to have a member called num, but the compiler doesn't know that t is internally pointing to a Literal.
    How should I access Literal `s data or functions from the pointer t itself ?

  2. #2
    C++ Witch laserlight's Avatar
    Join Date
    Oct 2003
    Location
    Singapore
    Posts
    28,413
    Ideally, t should have been a Literal* instead of a token*. If you must, then cast. Use static_cast if you are absolutely sure, on pain of death, that t points to a Literal, otherwise use dynamic_cast (and check for a null pointer or exception, as the case may be).
    Quote Originally Posted by Bjarne Stroustrup (2000-10-14)
    I get maybe two dozen requests for help with some sort of programming or design problem every day. Most have more sense than to send me hundreds of lines of code. If they do, I ask them to find the smallest example that exhibits the problem and send me that. Mostly, they then find the error themselves. "Finding the smallest program that demonstrates the error" is a powerful debugging tool.
    Look up a C++ Reference and learn How To Ask Questions The Smart Way

  3. #3
    Registered User
    Join Date
    Aug 2003
    Posts
    127
    Code:
    class Literal : public token
    {
    public:
        Literal(const std::string & str)
        {
            num_ = str to number;
        }
    
        int number() const { return num_; }
    private:
        int num_;
    };
    
    token* t = token_factory("7479");
    Literal * l = dynamic_cast<Literal*>(t);
    Nana C++ Library is a GUI framework that designed to be C++ style, cross-platform and easy-to-use.

  4. #4
    [](){}(); manasij7479's Avatar
    Join Date
    Feb 2011
    Location
    *nullptr
    Posts
    2,657
    Quote Originally Posted by laserlight View Post
    Ideally, t should have been a Literal* instead of a token*. If you must, then cast. Use static_cast if you are absolutely sure, on pain of death, that t points to a Literal, otherwise use dynamic_cast (and check for a null pointer or exception, as the case may be).
    Unfortunately, the ideal case can't be achieved, because I have to store different types of token* s into some container.

    The token_factory() also modifies an enum in the base class, by which the type of the derived class can be checked.
    So..would the following be appropriate?
    Code:
    if(t->type==literal)
        cout<<(static_cast<Literal*>(t))->num;

  5. #5
    C++ Witch laserlight's Avatar
    Join Date
    Oct 2003
    Location
    Singapore
    Posts
    28,413
    Yes, you could do that. dynamic_cast would also do something similiar, but you have better guarantee of performance with your enum check than relying on dynamic_cast, at the cost of having to do the check yourself.

    Another option is to provide the base class with an appropriate interface then use polymorphism, but it does not seem to apply here (though it applies if you are willing to overload operator<< for this for printing).
    Quote Originally Posted by Bjarne Stroustrup (2000-10-14)
    I get maybe two dozen requests for help with some sort of programming or design problem every day. Most have more sense than to send me hundreds of lines of code. If they do, I ask them to find the smallest example that exhibits the problem and send me that. Mostly, they then find the error themselves. "Finding the smallest program that demonstrates the error" is a powerful debugging tool.
    Look up a C++ Reference and learn How To Ask Questions The Smart Way

  6. #6
    Registered User
    Join Date
    Aug 2010
    Location
    Poland
    Posts
    733
    There is yet another solution, which I recall to use, to make token class an interface containing virtual GetInteger(), virtual GetReal(), etc. The default behaviour of these methods is to throw an exception "Cannot convert to an integer", "Cannot convert to a real number". Derieved classes shall override the appropriate methods. For example, an integer token shall override GetInteger(), but may also override GetString() (if you want an implicit conversion from integer to string). No dynamic_casts needed, but the scalability of such a solution is arguable.

    EDIT: a bit too late
    Last edited by kmdv; 08-22-2011 at 04:26 AM.

  7. #7
    [](){}(); manasij7479's Avatar
    Join Date
    Feb 2011
    Location
    *nullptr
    Posts
    2,657
    Quote Originally Posted by kmdv View Post
    There is yet another solution, which I recall to use, to make token class an interface containing virtual GetInteger(), virtual GetReal(), etc. The default behaviour of these methods is to throw an exception "Cannot convert to an integer", "Cannot convert to a real number". Derieved classes shall override the appropriate methods. For example, an integer token shall override GetInteger(), but may also override GetString() (if you want an implicit conversion from integer to string). No dynamic_casts needed, but the scalability of such a solution is arguable.
    I didn't think of that.
    But it could potentially get messy when I have at least 5 subclasses involved. (Is that what you meant by scalability?)

  8. #8
    Registered User
    Join Date
    Aug 2010
    Location
    Poland
    Posts
    733
    Scalability is about how much functionality you can add/change to the existing code.

    Whether it gets messy or not, depends on what you want to add. If the tokens are supposed to work with the existing data types (bool, int, float), it is very likely that you will not need to change the base interface at all. The matter is different if you decide to add a new token type having 'double' or 'unsigned int', which the interface is not supposed to work with.

  9. #9
    [](){}(); manasij7479's Avatar
    Join Date
    Feb 2011
    Location
    *nullptr
    Posts
    2,657
    Quote Originally Posted by kmdv View Post
    Scalability is about how much functionality you can add/change to the existing code.

    Whether it gets messy or not, depends on what you want to add. If the tokens are supposed to work with the existing data types (bool, int, float), it is very likely that you will not need to change the base interface at all. The matter is different if you decide to add a new token type having 'double' or 'unsigned int', which the interface is not supposed to work with.
    The token types I have are
    Keywords, Identifiers, Operators, Literals and Punctuators .

    Only literals and identifiers need to work with (by that I mean..could potentially contain) existing data types.
    So, In their respective declarations I've put an enumerator, to keep track of the data type and also unions( or separate variables) where the data would actually be stored.

  10. #10
    Registered User
    Join Date
    Aug 2003
    Posts
    127
    I have no idea what your purpose is. If it is a weak-type interpreter, the polymorphism method is a better solution to this suituation.

    >>Only literals and identifiers need to work with (by that I mean..could potentially contain) existing data types.
    In my opinion, the design gets involved between lexical analyzer and executor. Use an integer or enum type to present tokens, and build a semantic tree to execute the script by using class(object-orientied).
    Nana C++ Library is a GUI framework that designed to be C++ style, cross-platform and easy-to-use.

  11. #11
    [](){}(); manasij7479's Avatar
    Join Date
    Feb 2011
    Location
    *nullptr
    Posts
    2,657
    Thanks to all of you, the entire 'token' family is ready now..(except the implementations of the operator functions...but it'd be easy)

    Quote Originally Posted by jinhao
    build a semantic tree to execute the script by using class(object-orientied).
    Unfortunately...that is the point I'm having troubles at...(..but that is a topic for another thread after my mid term exams are over)
    I came up with the idea of a parse tree(sort of) but it doesn't seem to (at first glance...because my knowledge of the topic is quite shallow) fit with any thing about parsing I'd read before.
    I'm yet to decide whether to implement that or go with some well known algorithm.

Popular pages Recent additions subscribe to a feed

Similar Threads

  1. Can a macro evaluate ("return") a string?
    By monk64 in forum C Programming
    Replies: 1
    Last Post: 04-21-2010, 11:19 PM
  2. c++ equivalent for C#'s "sealed override"?
    By m37h0d in forum C++ Programming
    Replies: 56
    Last Post: 12-19-2009, 12:20 AM
  3. "itoa"-"_itoa" , "inp"-"_inp", Why some functions have "
    By L.O.K. in forum Windows Programming
    Replies: 5
    Last Post: 12-08-2002, 08:25 AM
  4. "CWnd"-"HWnd","CBitmap"-"HBitmap"...., What is mean by "
    By L.O.K. in forum Windows Programming
    Replies: 2
    Last Post: 12-04-2002, 07:59 AM
  5. Equivalent of Java's "super" keyword
    By JasonLikesJava in forum C++ Programming
    Replies: 6
    Last Post: 05-31-2002, 10:21 AM