slightly interresting derrived class problem

E

easy

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?
 
U

Ulrich Hobelmann

easy said:
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?
 
P

Puppet_Sock

easy said:
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
 
V

Victor Bazarov

easy said:
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
 
L

Luke Meyers

Ulrich said:
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
 
E

easy

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.
 
E

easy

"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.
 
A

Alf P. Steinbach

* 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
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.
 
L

Luke Meyers

easy said:
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
 
U

Ulrich Hobelmann

Luke said:
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 ;)
 

Ask a Question

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

You'll need to choose a username for the site, which only take a couple of moments. After that, you can post your question and our members will help you out.

Ask a Question

Members online

Forum statistics

Threads
473,755
Messages
2,569,536
Members
45,007
Latest member
obedient dusk

Latest Threads

Top