Static members and inheritance

A

Alex

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!
 
N

n.luke.meyers

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::eek:perator[] 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
 
A

Alex

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

Luke Meyers

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
 
A

Alex

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

Luke Meyers

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
 
J

Jim Langston

Alex said:
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 )
 
A

Alex

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.
 

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

No members online now.

Forum statistics

Threads
473,981
Messages
2,570,188
Members
46,731
Latest member
MarcyGipso

Latest Threads

Top