473,402 Members | 2,053 Online
Bytes | Software Development & Data Engineering Community
Post Job

Home Posts Topics Members FAQ

Join Bytes to post your question to a community of 473,402 software developers and data experts.

Static Class Variables, Inheritance, and Polymorphism

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
8 2863
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

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
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
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
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
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
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
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 thread has been closed and replies have been disabled. Please start a new discussion.

Similar topics

10
by: Angus Leeming | last post by:
Hello, Could someone explain to me why the Standard conveners chose to typedef std::string rather than derive it from std::basic_string<char, ...>? The result of course is that it is...
10
by: cppaddict | last post by:
Hi, Say I have a abstract base class and I know that every derived class will have a static data member (call it SharedInformation) representing information to be shared across all instances of...
4
by: PengYu.UT | last post by:
Hi, Some dynamic polymorphism programs can be converted to the equavalent static polymorphism programs. I'm wondering if there are any generall procedures that I can use to do this conversion. ...
3
by: Dave | last post by:
Hi, Is there a general rule to use 'static' on a class member? It seems uneccessary to have to create an instance of an object just to use it's methods where declaring something as static makes...
4
by: Bryan Green | last post by:
So I'm working on a project for a C# class I'm taking, where I need to keep some running totals via static variables. I need three classes for three different types of objects. The base class and...
7
by: WXS | last post by:
Vote for this idea if you like it here: http://lab.msdn.microsoft.com/productfeedback/viewfeedback.aspx?feedbackid=5fee280d-085e-4fe2-af35-254fbbe96ee9...
4
by: Chukkalove | last post by:
Hi I have an abstract class that contains 100% static methods and variables. One of the member variables "string DatabaseName" needs to be overridden in derived classes. Am I able to keep my...
4
by: DBC User | last post by:
I have a class with bunch of static methods. I could regourp all the static methods into seperate 3 or 4 classes. I was thinking about using Singlton pattern for all these 4 classes so that it...
9
by: Steve Richter | last post by:
in a generic class, can I code the class so that I can call a static method of the generic class T? In the ConvertFrom method of the generic TypeConvert class I want to write, I have a call to...
0
by: Charles Arthur | last post by:
How do i turn on java script on a villaon, callus and itel keypad mobile phone
0
by: emmanuelkatto | last post by:
Hi All, I am Emmanuel katto from Uganda. I want to ask what challenges you've faced while migrating a website to cloud. Please let me know. Thanks! Emmanuel
0
BarryA
by: BarryA | last post by:
What are the essential steps and strategies outlined in the Data Structures and Algorithms (DSA) roadmap for aspiring data scientists? How can individuals effectively utilize this roadmap to progress...
1
by: Sonnysonu | last post by:
This is the data of csv file 1 2 3 1 2 3 1 2 3 1 2 3 2 3 2 3 3 the lengths should be different i have to store the data by column-wise with in the specific length. suppose the i have to...
0
by: Hystou | last post by:
There are some requirements for setting up RAID: 1. The motherboard and BIOS support RAID configuration. 2. The motherboard has 2 or more available SATA protocol SSD/HDD slots (including MSATA, M.2...
0
by: Hystou | last post by:
Most computers default to English, but sometimes we require a different language, especially when relocating. Forgot to request a specific language before your computer shipped? No problem! You can...
0
by: Hystou | last post by:
Overview: Windows 11 and 10 have less user interface control over operating system update behaviour than previous versions of Windows. In Windows 11 and 10, there is no way to turn off the Windows...
0
agi2029
by: agi2029 | last post by:
Let's talk about the concept of autonomous AI software engineers and no-code agents. These AIs are designed to manage the entire lifecycle of a software development project—planning, coding, testing,...
0
isladogs
by: isladogs | last post by:
The next Access Europe User Group meeting will be on Wednesday 1 May 2024 starting at 18:00 UK time (6PM UTC+1) and finishing by 19:30 (7.30PM). In this session, we are pleased to welcome a new...

By using Bytes.com and it's services, you agree to our Privacy Policy and Terms of Use.

To disable or enable advertisements and analytics tracking please visit the manage ads & tracking page.