slightly interresting derrived class problem

Discussion in 'C++' started by easy, May 29, 2006.

  1. easy

    easy Guest

    I start off with an interface class that has no data members and a
    handful of virtual functions.


    First Question: is that allowed ?


    I then derived from this class and it gets included into a couple of
    other classes that need that interface. The derived class had a number
    of data members including a struct that allow it to do its dirty work.

    When I directly access any data members (through pointers or through
    public data members) in the derrived class hilarity ensues. I found
    that the value returned is offset by 4 bytes( 32bits ).

    for example, if I wanted:
    class1.public_struct.int0
    I would get
    class1.public_struct.int1


    more curiously this problem would only show up when i ran the release
    version of the code. The debug version behaved correctly.

    After an entire wasted morning I added an unused data member to the
    very first interface class and all problems dissapeared like a fart in
    the wind.

    Main Question: Is this a compiler error or did I violate the standard?
     
    easy, May 29, 2006
    #1
    1. Advertising

  2. easy wrote:
    > I start off with an interface class that has no data members and a
    > handful of virtual functions.
    >
    >
    > First Question: is that allowed ?


    Sure, why not? A class can (I think) be empty, or it can contain a
    number of variables and/or functions (including virtual ones).

    > I then derived from this class and it gets included into a couple of
    > other classes that need that interface. The derived class had a number
    > of data members including a struct that allow it to do its dirty work.
    >
    > When I directly access any data members (through pointers or through
    > public data members) in the derrived class hilarity ensues. I found
    > that the value returned is offset by 4 bytes( 32bits ).


    First of all, see if you can live without public members. Some get/set
    functions might be a lot cleaner.

    And it'd be great if you could describe what exactly explodes in your
    code when you access a public member. If you use the GNU compiler, you
    could even try to compile it with optimization AND debug (-g -O2 for
    instance), to see if the bug appears.

    > for example, if I wanted:
    > class1.public_struct.int0
    > I would get
    > class1.public_struct.int1


    Is class1 the derived class, or are you doing something with the base class?
     
    Ulrich Hobelmann, May 29, 2006
    #2
    1. Advertising

  3. easy

    Puppet_Sock Guest

    easy wrote:
    > I start off with an interface class that has no data members and a
    > handful of virtual functions.
    >
    > First Question: is that allowed ?


    If you do it correctly, yes.

    > I then derived from this class and it gets included into a couple of
    > other classes that need that interface. The derived class had a number
    > of data members including a struct that allow it to do its dirty work.


    Whoo hoo! Dirty work? Ok.

    > When I directly access any data members (through pointers or through
    > public data members) in the derrived class hilarity ensues. I found
    > that the value returned is offset by 4 bytes( 32bits ).
    >
    > for example, if I wanted:
    > class1.public_struct.int0
    > I would get
    > class1.public_struct.int1
    >
    > more curiously this problem would only show up when i ran the release
    > version of the code. The debug version behaved correctly.
    >
    > After an entire wasted morning I added an unused data member to the
    > very first interface class and all problems dissapeared like a fart in
    > the wind.
    >
    > Main Question: Is this a compiler error or did I violate the standard?


    It sounds like you've got some kind of data slicing going on. Some
    place in there, your pointer thinks it's pointing at a different kind
    of
    object from what it is actually pointing at. The result is, when it
    tries to find int0 it is looking where it expects int0, but it has
    found
    instead int1. (Or the other way over.)

    In debug mode, there may be other stuff in there that shoves stuff
    around by amounts that are not defined in the standard. It could
    quite easily be that the base class is shoved forward 4 bytes, and
    the derived by 8. And so when you make your off-by-4 errror, it
    gets another error in the other direction from the debug info.

    Post a minimal compilable code sample that shows the problem,
    and we may be able to help.
    Socks
     
    Puppet_Sock, May 29, 2006
    #3
  4. easy wrote:
    > I start off with an interface class that has no data members and a
    > handful of virtual functions.
    >
    >
    > First Question: is that allowed ?


    Uh... Yes. Does your compiler tell you something you don't believe
    it should?

    > I then derived from this class and it gets included into a couple of
    > other classes that need that interface. The derived class had a
    > number of data members including a struct that allow it to do its
    > dirty work.


    OK...

    > When I directly access any data members (through pointers or through
    > public data members) in the derrived class hilarity ensues. I found
    > that the value returned is offset by 4 bytes( 32bits ).
    >
    > for example, if I wanted:
    > class1.public_struct.int0
    > I would get
    > class1.public_struct.int1


    That's bizarre.

    > more curiously this problem would only show up when i ran the release
    > version of the code. The debug version behaved correctly.


    That sounds like an error in the compiler...

    > After an entire wasted morning I added an unused data member to the
    > very first interface class and all problems dissapeared like a fart in
    > the wind.
    >
    > Main Question: Is this a compiler error or did I violate the standard?


    To be able to tell you for sure, we'd need to see the code.

    V
    --
    Please remove capital 'A's when replying by e-mail
    I do not respond to top-posted replies, please don't ask
     
    Victor Bazarov, May 29, 2006
    #4
  5. easy

    Luke Meyers Guest

    Ulrich Hobelmann wrote:
    > easy wrote:
    > > I start off with an interface class that has no data members and a
    > > handful of virtual functions.
    > >
    > > First Question: is that allowed ?

    >
    > Sure, why not? A class can (I think) be empty, or it can contain a
    > number of variables and/or functions (including virtual ones).


    Definitely. It's a very common idiom. However, some gurus (read:
    Sutter) recommend preferring to avoid public virtual functions. See
    _Exceptional C++ Style_ for full exposition, but basically the
    reasoning is that with public virtual functions, you're combining two
    interfaces into one, which is an unnecessary form of coupling and hence
    needlessly restrictive. The first interface is the base class's public
    interface; the second interface (in a slightly different sense of the
    word) is the "customization interface" presented to derived classes.
    Two different audiences.

    What he recommends instead is to use simple forwarding in trivial
    cases, and to make use of idioms such as the Template Method pattern in
    more complex cases. For example:

    class Base
    {
    public:
    void doStuff() { reallyDoStuff(); }
    protected:
    virtual void reallyDoStuff();
    };

    It may seem at first that you'd rarely get beyond such trivial cases
    and really wind up using Template Method a lot, but that's a result of
    being stuck in the mindset of combining these two interfaces. A member
    function corresponds to a responsibility -- surely it happens quite
    frequently that there is not a 1:1 mapping between publicly visible
    responsibilities and behavior intended to be customized by subclasses!

    > First of all, see if you can live without public members. Some get/set
    > functions might be a lot cleaner.


    I agree on the public members -- except in behaviorless structs,
    they're generally to be avoided. However, I disagree with simply
    replacing your "int x" public data with "int getX()" and "void
    setX(int)." There are some arguments as to how this is better than
    simple public data, but whatever advantages exist simply aren't enough.
    The real answer is design -- put the data where it wants to be. Don't
    provide data, provide computation. I'd go into this more, but you can
    google something like "getters setters evil" for more.

    Luke
     
    Luke Meyers, May 30, 2006
    #5
  6. easy

    easy Guest

    Would it be better if I posted some files to some webspace or copied
    the contents to the forum? Either way I'll post tomorrow when I get
    back to work.
     
    easy, May 30, 2006
    #6
  7. easy

    easy Guest

    "First of all, see if you can live without public members. Some
    get/set functions might be a lot cleaner."

    The public members were only used by me to try and figure out what the
    hell was going on.
     
    easy, May 30, 2006
    #7
  8. * easy:
    > I start off with an interface class that has no data members and a
    > handful of virtual functions.
    >
    > First Question: is that allowed ?


    Yes.


    > I then derived from this class and it gets included into a couple of
    > other classes that need that interface. The derived class had a number
    > of data members including a struct that allow it to do its dirty work.
    >
    > When I directly access any data members (through pointers or through
    > public data members) in the derrived class hilarity ensues. I found
    > that the value returned is offset by 4 bytes( 32bits ).
    >
    > for example, if I wanted:
    > class1.public_struct.int0
    > I would get
    > class1.public_struct.int1
    >
    >
    > more curiously this problem would only show up when i ran the release
    > version of the code. The debug version behaved correctly.


    Post a minimal example that compiles.

    For other requirements on posting example code, see the FAQ item "How do
    I post a question about code that doesn't work correctly?", currently at
    <url: http://www.parashift.com/c++-faq-lite/how-to-post.html#faq-5.8>.


    > After an entire wasted morning I added an unused data member to the
    > very first interface class and all problems dissapeared like a fart in
    > the wind.
    >
    > Main Question: Is this a compiler error or did I violate the standard?


    Probably the latter, but not in the way you indicated above.

    --
    A: Because it messes up the order in which people normally read text.
    Q: Why is it such a bad thing?
    A: Top-posting.
    Q: What is the most annoying thing on usenet and in e-mail?
     
    Alf P. Steinbach, May 30, 2006
    #8
  9. easy

    Luke Meyers Guest

    easy wrote:
    > Would it be better if I posted some files to some webspace or copied
    > the contents to the forum? Either way I'll post tomorrow when I get
    > back to work.


    Please quote the post you're replying to, as a matter of longstanding
    Usenet conventional courtesy.

    You should post your source code directly to the newsgroup -- however,
    it's important to post a *minimal* example that demonstrates the
    problem. Most problems appropriate for newsgroup discussion can be
    described in a page or so of code. *Compilable* code, mind.

    Luke
     
    Luke Meyers, May 30, 2006
    #9
  10. Luke Meyers wrote:
    > Definitely. It's a very common idiom. However, some gurus (read:
    > Sutter) recommend preferring to avoid public virtual functions. See
    > _Exceptional C++ Style_ for full exposition, but basically the
    > reasoning is that with public virtual functions, you're combining two
    > interfaces into one, which is an unnecessary form of coupling and hence
    > needlessly restrictive. The first interface is the base class's public
    > interface; the second interface (in a slightly different sense of the
    > word) is the "customization interface" presented to derived classes.
    > Two different audiences.


    Hm, interesting view. Coming from a Java background, I'd rather say
    that the whole point of virtual functions is being public. A set of
    virtual functions is the base class's interface that other classes can
    implement. So, I don't think they are harmful (even if usually I
    strongly prefer non-virtual functions and composition when possible,
    both for performance and for clarity).

    I'd be careful with (non-virtual) inheritance (i.e. with not
    implementing a clear, documented interface).

    > I agree on the public members -- except in behaviorless structs,
    > they're generally to be avoided. However, I disagree with simply
    > replacing your "int x" public data with "int getX()" and "void
    > setX(int)." There are some arguments as to how this is better than
    > simple public data, but whatever advantages exist simply aren't enough.
    > The real answer is design -- put the data where it wants to be. Don't
    > provide data, provide computation. I'd go into this more, but you can
    > google something like "getters setters evil" for more.


    Cool, thanks for the link; I'll look into it. Myself, I sometimes avoid
    get/setters (and use structs instead), just for convenience, but I
    thought I should mention the "official" view ;)
     
    Ulrich Hobelmann, May 30, 2006
    #10
    1. Advertising

Want to reply to this thread or ask your own question?

It takes just 2 minutes to sign up (and it's free!). Just click the sign up button to choose a username and then you can ask your own questions on the forum.
Similar Threads
  1. Simon Harris

    Class Basics (Slightly OT?)

    Simon Harris, May 8, 2005, in forum: ASP .Net
    Replies:
    5
    Views:
    377
    Web Team @ Borough of Poole
    May 11, 2005
  2. E11
    Replies:
    1
    Views:
    4,958
    Thomas Weidenfeller
    Oct 12, 2005
  3. Jason Heyes
    Replies:
    16
    Views:
    576
    Jason Heyes
    Apr 3, 2005
  4. vdauthor
    Replies:
    4
    Views:
    633
    vdauthor
    Jan 4, 2007
  5. Chris Crowe [MVP]
    Replies:
    3
    Views:
    166
    Chris Crowe [MVP]
    Aug 24, 2005
Loading...

Share This Page