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

Static members and inheritance

P: n/a
Hello. I want to manage a class hierarchy with a static member (a
vector) in which some strings are stored depending on the Class:

class Base { // Abstract
....
typedef std::vector<std::string> nameVector_t;
public:
const nameVector_t& GetNames() { return names; }
protected:
virtual void SetNames()=0,
static nameVector_t names;
};

class House : public Base {

virtual void SetNames() {
names.push_back("Door");
names.push_back("Window");
names.push_back("Roof");
}

};
int main()
{
Base* p = new House;
p->SetNames();
std::cout << p->GetNames[1] << std::endl; // Should print "Window"
}
Is this OK? If not, how can I do something similiar?

Thanks!

Dec 24 '05 #1
Share this Question
Share on Google+
8 Replies


P: n/a
The call to p->SetNames is illegal because that member function is
protected within the enclosing context. I am also pretty sure you
can't index into the GetNames function -- did you leave out some
parens? And ISTR that std::vector::operator[] is non-const, right? So
you couldn't apply it to a const& like you're evidently trying to do.

Unless you plan to further inherit from House, House::SetNames need not
be virtual. Only the base class's member function needs that. Also,
it is illegal to declare it as private, as you have, since it is
protected in Base.

If SetNames is going to store strings in Base::names based only on the
class, not on member data, you should strongly consider making it a
static member function.

If you address these issues, your code should function as intended. I
think there are probably some better design choices that could be made
to accomplish the same or a similar result, though, depending on the
needs of the actual application. For example, if you intend to call
SetNames frequently, it would be more sensible to just update a
reference rather than performing vector manipulations. If the values
are known at compile time, take advantage. I'd have to know more about
what you're trying to do, though -- I don't see how this vector of
strings is going to help you "manage a class hierarchy."

L

Dec 24 '05 #2

P: n/a
Thanks for your response.

I wrote that code as an example in the previous message, it is not my
code, so there may be some errors which don't concern to what I was
trying to do.

That names are know at compile time and don't change duringe the
application. I had though of something similar to what you say...

class Base {
public:
virtual GetName(int id)=0;
}

class House {
GetName(int id) {
switch(id) {
case 1: return "Door"
case 2: return "Window"
...
}
}

But that way you have to redefine GetName for each subclass, instead of
inserting some string in a vector.

What do you think?

Dec 24 '05 #3

P: n/a
I meant

....
virtual const char* GetName(int id)=0;
....

Dec 24 '05 #4

P: n/a
I think this is getting closer to what you want. This will run a lot
faster and expresses your intent more clearly. If you don't want to
redefine GetName for every subclass, don't make it pure virtual, just
make it virtual and provide a default implementation. You'll have to
decide what constitutes appropriate default behavior, and what you do
if the user requests a name from an invalid index. Something like the
following:

#include <string>

class Base {
public:
virtual std::string const& getName(unsigned int id) { return
"Default"; }
}; // <-- don't forget semicolon here

class House : public Base {
public:
std::string const& GetName(unsigned int id) { // Make this virtual,
too, if you plan to inherit further from House
switch(id) {
case 1:
// . . .
break;
default:
return Base::getName(id);
}
}
};

Also, you should use real strings (as above), not char* (as in your
other follow-up post). Probably also an enum for the switch, etc.
That'll get you to about where you want to be. I'm still not convinced
it's the best approach, but it's at least straightforward and should do
what you want.

Luke

Dec 25 '05 #5

P: n/a
I am writing an application which draws objects using OpenGL. Objects
are editable with some dialogs and I need every object to be able to
identify its parts. The dialog class ask the object being edited for
its part names and some other things. That's why I need a generic way
of asking an object for its part number x.

Thanks for your help.

Dec 25 '05 #6

P: n/a
For that purpose, I would suggest that a random-indexing idiom is a
poor fit. Generally for "for each" behavior, you don't care what
particular index is involved, and you're better off if you can avoid
exposing that index in your code. Are the parts you refer to objects
themselves? If so, I would recommend the following:

struct Part {
virtual std::string getName() = 0; // possibly static, if same for
all members of a given subclass
};

class Base {
protected:
std::vector<Part> parts;
};

Then you can add methods to base which loop over the parts and perform
necessary operations. If you need the list of part names, use
std::transform onto a vector of strings. There are a lot of directions
you can take this, but this is where I'd start. If a part is an
important thing in your program and has associated state (its name),
why not represent it as an object? Forcing the enclosing object to
maintain that state produces unnecessary coupling.

Luke

Dec 26 '05 #7

P: n/a
"Alex" <ac******@gmail.com> wrote in message
news:11**********************@g14g2000cwa.googlegr oups.com...
Hello. I want to manage a class hierarchy with a static member (a
vector) in which some strings are stored depending on the Class:

class Base { // Abstract
...
typedef std::vector<std::string> nameVector_t;
public:
const nameVector_t& GetNames() { return names; }
protected:
virtual void SetNames()=0,
static nameVector_t names;
};

class House : public Base {

virtual void SetNames() {
names.push_back("Door");
names.push_back("Window");
names.push_back("Roof");
}

};
int main()
{
Base* p = new House;
p->SetNames();
std::cout << p->GetNames[1] << std::endl; // Should print "Window"
}
Is this OK? If not, how can I do something similiar?

Thanks!


I'm not quite positive what you are trying to do here, but in this case why
don't you just pass the array index into GetNames itself?

std::string GetName( int Index ) const { if ( Index < names.length() )
return names[Index] else return ""; }

( it may be names.count() for vectors, I don't remember )
Dec 26 '05 #8

P: n/a
Because I want names to be a static member, and that's the main
discussion here. I want it to be static but different for each subclass.

Dec 26 '05 #9

This discussion thread is closed

Replies have been disabled for this discussion.