By using this site, you agree to our updated Privacy Policy and our Terms of Use. Manage your Cookies Settings.
445,758 Members | 1,223 Online
Bytes IT Community
+ Ask a Question
Need help? Post your question and get tips & solutions from a community of 445,758 IT Pros & Developers. It's quick & easy.

Static Class Variables, Inheritance, and Polymorphism

P: n/a
Hi, I've got a base class and some derived classes that look something
like this:

class Base {
public:
int getType() { return type; }
private:
static const int type = 0;
};

class Derived1 : public Base {
private:
static const int type = 1;
};

class Derived2 : public Base {
private:
static const int type = 2;
};

I've then got a vector declared to hold instances of Base, but it's
actually filled with various instances of Derived1 and Derived2. On
iterating through and examining each item, I'd like to be able to call
getType() and have the correct derived class's class variable
retrieved. However, I only get 0 returned. I've tried making
getType() virtual in the Base class, but that didn't help anything.

I can get this to work by defining getType() in each class to return a
literal 0, 1, or 2, but I'd think that what I'm trying do should
work. Any ideas? I don't want to dynamically cast if I can avoid it.

Thanks for any help! Let me know if I can frame the problem
differently or provide more info.

- Chris

Apr 3 '07 #1
Share this Question
Share on Google+
8 Replies


P: n/a
On 3 Apr., 18:45, "crjjrc" <crj...@gmail.comwrote:
Hi, I've got a base class and some derived classes that look something
like this:

class Base {
public:
int getType() { return type; }
private:
static const int type = 0;
};

class Derived1 : public Base {
private:
static const int type = 1;
};

class Derived2 : public Base {
private:
static const int type = 2;
};

I've then got a vector declared to hold instances of Base, but it's
actually filled with various instances of Derived1 and Derived2. On
iterating through and examining each item, I'd like to be able to call
getType() and have the correct derived class's class variable
retrieved. However, I only get 0 returned. I've tried making
getType() virtual in the Base class, but that didn't help anything.

I can get this to work by defining getType() in each class to return a
literal 0, 1, or 2, but I'd think that what I'm trying do should
work. Any ideas? I don't want to dynamically cast if I can avoid it.

Thanks for any help! Let me know if I can frame the problem
differently or provide more info.

- Chris
std::vector can not hold polymorphic types (and neither can any other
container). The trick is to use a vector of pointers, either directly
or (IMHO better) using some smart pointer type or using some external
library (I believe boost has special libraries implementing
pointercontainers).

/Peter

Apr 3 '07 #2

P: n/a

crjjrc wrote:
Hi, I've got a base class and some derived classes that look something
like this:

class Base {
public:
int getType() { return type; }
private:
static const int type = 0;
};

class Derived1 : public Base {
private:
static const int type = 1;
};

class Derived2 : public Base {
private:
static const int type = 2;
};

I've then got a vector declared to hold instances of Base, but it's
actually filled with various instances of Derived1 and Derived2. On
iterating through and examining each item, I'd like to be able to call
getType() and have the correct derived class's class variable
retrieved. However, I only get 0 returned. I've tried making
getType() virtual in the Base class, but that didn't help anything.

I can get this to work by defining getType() in each class to return a
literal 0, 1, or 2, but I'd think that what I'm trying do should
work. Any ideas? I don't want to dynamically cast if I can avoid it.

Thanks for any help! Let me know if I can frame the problem
differently or provide more info.

- Chris
class Base {
public:
virtual int getType() { return type; }
private:
static const int type = 0;
};

class Derived1 : public Base {
private:
static const int type = 1;
public:
int getType() { return type; }
};

class Derived2 : public Base {
private:
static const int type = 2;
public:
int getType() { return type; }
};

int main(void) {
std::vector<Base*v;

v.push_back(new Derived1);
v.push_back(new Derived2);
v.push_back(new Derived2);
v.push_back(new Derived1);
v.push_back(new Base);

for (std::vector<Base*>::iterator i = v.begin(); i != v.end(); ++i){
std::cout << (*i)->getType() << std::endl;
}

return 0;
}

I guess I'm assuming you actually want Base to be a non-abstract
class... you may want to have base look more like

class Base {
public:
virtual int getType()=0;
};
and remember now you are not allowed to instantiate Base directly...

Apr 3 '07 #3

P: n/a
crjjrc wrote:
Hi, I've got a base class and some derived classes that look something
like this:

class Base {
public:
int getType() { return type; }
private:
static const int type = 0;
};

class Derived1 : public Base {
private:
static const int type = 1;
};

class Derived2 : public Base {
private:
static const int type = 2;
};

I've then got a vector declared to hold instances of Base, but it's
actually filled with various instances of Derived1 and Derived2. On
iterating through and examining each item, I'd like to be able to call
getType() and have the correct derived class's class variable
retrieved. However, I only get 0 returned. I've tried making
getType() virtual in the Base class, but that didn't help anything.

I can get this to work by defining getType() in each class to return a
literal 0, 1, or 2, but I'd think that what I'm trying do should
work. Any ideas? I don't want to dynamically cast if I can avoid it.

Thanks for any help! Let me know if I can frame the problem
differently or provide more info.

- Chris
Since you didn't post a complete code, I am guess it's most likely due
to the way you declare your vector container, as it's been explained by
other people. It's a good idea to post a compilable code that
demonstrate your problem.

Fei
Apr 3 '07 #4

P: n/a
On Apr 3, 12:45 pm, "crjjrc" <crj...@gmail.comwrote:
Hi, I've got a base class and some derived classes that look something
like this:

class Base {
public:
int getType() { return type; }
private:
static const int type = 0;
};

class Derived1 : public Base {
private:
static const int type = 1;
};

class Derived2 : public Base {
private:
static const int type = 2;
};

I've then got a vector declared to hold instances of Base, but it's
actually filled with various instances of Derived1 and Derived2. On
iterating through and examining each item, I'd like to be able to call
getType() and have the correct derived class's class variable
retrieved. However, I only get 0 returned. I've tried making
getType() virtual in the Base class, but that didn't help anything.

I can get this to work by defining getType() in each class to return a
literal 0, 1, or 2, but I'd think that what I'm trying do should
work. Any ideas? I don't want to dynamically cast if I can avoid it.

Thanks for any help! Let me know if I can frame the problem
differently or provide more info.

- Chris

i would ....

class base {
public:
int getType() const { return 0; }
}

class drv1 {
public:
int getType() const { return 1; }
}
..
.. same for others
..

then

vector< Base* >



Apr 4 '07 #5

P: n/a
On Apr 3, 1:31 pm, "bjeremy" <bjer...@sbcglobal.netwrote:
I've then got a vector declared to hold instances of Base, but it's
actually filled with various instances of Derived1 and Derived2. On
iterating through and examining each item, I'd like to be able to call
getType() and have the correct derived class's class variable
retrieved. However, I only get 0 returned. I've tried making
getType() virtual in the Base class, but that didn't help anything.

class Base {
public:
virtual int getType() { return type; }
private:
static const int type = 0;
};

class Derived1 : public Base {
private:
static const int type = 1;
public:
int getType() { return type; }
};

class Derived2 : public Base {
private:
static const int type = 2;
public:
int getType() { return type; }
};
This is almost identical to what I had, but I didn't define getType
for each derivation, and I only got 0 returned from getType(). I
don't see why getType needs to be defined for each derived class. It
seems like the parent's getType should pull the variable type from the
child for instances of Derived1 and Derived2. type should be a
"virtual" member, I would think. Is this not the case?

- Chris

Apr 4 '07 #6

P: n/a
On Apr 4, 7:50 pm, "crjjrc" <crj...@gmail.comwrote:
On Apr 3, 1:31 pm, "bjeremy" <bjer...@sbcglobal.netwrote:
I've then got a vector declared to hold instances of Base, but it's
actually filled with various instances of Derived1 and Derived2.
No it's not. A vector always holds instances of the type it was
declared with. If you declare std::vector<Base>, it will hold
instances of Base, and nothing else. This is one of the most
important invariants of std::vector.
On
iterating through and examining each item, I'd like to be able to call
getType() and have the correct derived class's class variable
retrieved. However, I only get 0 returned. I've tried making
getType() virtual in the Base class, but that didn't help anything.
class Base {
public:
virtual int getType() { return type; }
private:
static const int type = 0;
};
class Derived1 : public Base {
private:
static const int type = 1;
public:
int getType() { return type; }
};
class Derived2 : public Base {
private:
static const int type = 2;
public:
int getType() { return type; }
};
This is almost identical to what I had, but I didn't define getType
for each derivation, and I only got 0 returned from getType(). I
don't see why getType needs to be defined for each derived class.
Because it's supposed to do something different in each class.
In Base, it returns Base::type, and in Derived1, it returns
Derived1::type. For what you seem to expect, type would have to
be virtual, which isn't possible for two reasons: data types
can't be virtual, and static members can't be virtual.
It
seems like the parent's getType should pull the variable type from the
child for instances of Derived1 and Derived2. type should be a
"virtual" member, I would think.
Why? You haven't declared it virtual. For various reasons, in
fact, data members can't be virtual; only functions. And of
course, static members can't be virtual. Perhaps the reason
data members can't be virtual is because it only makes sense for
static data members; the reason static members can't be virtual
is that virtuality is based on the actual (dynamic) type of the
object, and static members don't have an associated object, so
it doesn't make sense either.

One possible solution here (other than providing the function in
all of the subclasses, which is still probably the best idea) is
to create a non-static member type in the base class, and have
the derived classes pass its value as an argument to the
constructor of Base.

--
James Kanze (GABI Software) email:ja*********@gmail.com
Conseils en informatique orientée objet/
Beratung in objektorientierter Datenverarbeitung
9 place Sémard, 78210 St.-Cyr-l'École, France, +33 (0)1 30 23 00 34

Apr 5 '07 #7

P: n/a
On Apr 5, 4:53 am, "James Kanze" <james.ka...@gmail.comwrote:
I've then got a vector declared to hold instances of Base, but it's
actually filled with various instances of Derived1 and Derived2.

No it's not. A vector always holds instances of the type it was
declared with. If you declare std::vector<Base>, it will hold
instances of Base, and nothing else. This is one of the most
important invariants of std::vector.
I should have clarified -- I declared a vector to hold pointers to
instances of Base.
It
seems like the parent's getType should pull the variable type from the
child for instances of Derived1 and Derived2. type should be a
"virtual" member, I would think.

Why? You haven't declared it virtual.
In my first post, I said I tried declaring getType() as virtual.
For various reasons, in
fact, data members can't be virtual; only functions. And of
course, static members can't be virtual. Perhaps the reason
data members can't be virtual is because it only makes sense for
static data members; the reason static members can't be virtual
is that virtuality is based on the actual (dynamic) type of the
object, and static members don't have an associated object, so
it doesn't make sense either.
I believe this last comment contains an inconsistency. You say that
virtuality is based on class, but since static members don't have an
associated instance, virtuality doesn't make sense. Well, static
members do have an associated class. If I've got an object of a
derived class, I'd argue that I should be able to access the type
member of the respective class without having to replicate the exact
same function in all derived classes. If I called a virtual function
in the parent's getType(), would I not access the definition of the
function in the derived class? And this function is associated not
with a particular object, but with the object's class. A consistent
language should use overridden members just as they use overridden
functions. Why should data and code be treated differently? This is
a serious question. I'm not trying to argue, and I'd like to really
know why this is the case.

Nevertheless, C++ isn't designed this way. I don't see a compelling
reason why it is not. My solution mentioned in my first post just
avoids members altogether, with functions that return a literal in
each derived class. That makes the most sense for what I need to do.

- Chris

Apr 5 '07 #8

P: n/a
On Apr 5, 3:37 pm, "crjjrc" <crj...@gmail.comwrote:
On Apr 5, 4:53 am, "James Kanze" <james.ka...@gmail.comwrote:
I've then got a vector declared to hold instances of Base, but it's
actually filled with various instances of Derived1 and Derived2.
No it's not. A vector always holds instances of the type it was
declared with. If you declare std::vector<Base>, it will hold
instances of Base, and nothing else. This is one of the most
important invariants of std::vector.
I should have clarified -- I declared a vector to hold pointers to
instances of Base.
Yes. You should have been precise. Precision is an important
quality when programming.
It
seems like the parent's getType should pull the variable type from the
child for instances of Derived1 and Derived2. type should be a
"virtual" member, I would think.
Why? You haven't declared it virtual.
In my first post, I said I tried declaring getType() as virtual.
And if you override getType() in the derived classes, the
overriding version gets called, no.
For various reasons, in
fact, data members can't be virtual; only functions. And of
course, static members can't be virtual. Perhaps the reason
data members can't be virtual is because it only makes sense for
static data members; the reason static members can't be virtual
is that virtuality is based on the actual (dynamic) type of the
object, and static members don't have an associated object, so
it doesn't make sense either.
I believe this last comment contains an inconsistency. You say that
virtuality is based on class, but since static members don't have an
associated instance, virtuality doesn't make sense.
Virtual resolution is based on the dynamic type of the actual
*object*, not on the static type (the class) that the compiler
sees.
Well, static members do have an associated class.
But they don't have an associated object. So what do you base
the dynamic type on?
If I've got an object of a
derived class, I'd argue that I should be able to access the type
member of the respective class without having to replicate the exact
same function in all derived classes.
In sum, you're arguing for virtual data members. The language
doesn't support them, for various reasons. If you think it
should, write up a proposal, with a detailed and precise
explination of 1) what the benefits of this are, and 2) how it
can be implemented, and the committee will doubtlessly consider
it. (Actually, implementation is fairly trivial, but for the
moment, I fail to see any real benefits, and I can see a lot of
dangers in it.)
If I called a virtual function
in the parent's getType(), would I not access the definition of the
function in the derived class?
Yes. If you declare the function virtual in the base class.
And this function is associated not
with a particular object, but with the object's class.
When you call a non-static member function, you associate it
with an object.
A consistent
language should use overridden members just as they use overridden
functions.
C++ does. You didn't declare the data element virtual, so it is
not treated as virtual.
Why should data and code be treated differently?
It isn't, in C++. Except, of course, that you cannot declare
data virtual.
This is
a serious question. I'm not trying to argue, and I'd like to really
know why this is the case.
Nevertheless, C++ isn't designed this way. I don't see a compelling
reason why it is not. My solution mentioned in my first post just
avoids members altogether, with functions that return a literal in
each derived class. That makes the most sense for what I need to do.
That's the usual solution. The general philosophy in an OO-type
class is that data is an implementation detail of the class
itself; all that counts is functions. One can argue whether
this is right or not, but there is certainly historical
precedent: I don't know of any language which supports
polymorphism on data types.

--
James Kanze (Gabi Software) email: ja*********@gmail.com
Conseils en informatique orientée objet/
Beratung in objektorientierter Datenverarbeitung
9 place Sémard, 78210 St.-Cyr-l'École, France, +33 (0)1 30 23 00 34

Apr 5 '07 #9

This discussion thread is closed

Replies have been disabled for this discussion.