Static members and inheritance

Discussion in 'C++' started by Alex, Dec 24, 2005.

  1. Alex

    Alex Guest

    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!
     
    Alex, Dec 24, 2005
    #1
    1. Advertising

  2. Alex

    Guest

    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
     
    , Dec 24, 2005
    #2
    1. Advertising

  3. Alex

    Alex Guest

    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?
     
    Alex, Dec 24, 2005
    #3
  4. Alex

    Alex Guest

    I meant

    ....
    virtual const char* GetName(int id)=0;
    ....
     
    Alex, Dec 24, 2005
    #4
  5. Alex

    Luke Meyers Guest

    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
     
    Luke Meyers, Dec 25, 2005
    #5
  6. Alex

    Alex Guest

    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.
     
    Alex, Dec 25, 2005
    #6
  7. Alex

    Luke Meyers Guest

    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
     
    Luke Meyers, Dec 26, 2005
    #7
  8. Alex

    Jim Langston Guest

    "Alex" <> wrote in message
    news:...
    > 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 )
     
    Jim Langston, Dec 26, 2005
    #8
  9. Alex

    Alex Guest

    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.
     
    Alex, Dec 26, 2005
    #9
    1. Advertising

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

It takes just 2 minutes to sign up (and it's free!). Just click the sign up button to choose a username and then you can ask your own questions on the forum.
Similar Threads
  1. JFCM
    Replies:
    4
    Views:
    5,741
  2. cppaddict

    Static Members and Inheritance

    cppaddict, May 16, 2004, in forum: C++
    Replies:
    10
    Views:
    7,163
    jeffc
    May 17, 2004
  3. Fabian PyDEV
    Replies:
    0
    Views:
    124
    Fabian PyDEV
    Apr 2, 2013
  4. Dave Angel
    Replies:
    0
    Views:
    132
    Dave Angel
    Apr 2, 2013
  5. Arnaud Delobelle
    Replies:
    0
    Views:
    127
    Arnaud Delobelle
    Apr 2, 2013
Loading...

Share This Page