tags:

views:

104

answers:

3

Is something similar to this possible? This way it produces an error.

class A {
    public:
    virtual std::string key;
};

class B : public A {
    public:
    std::string key;
};

int main()
{
    A a;
    a.key = "Foo";
    return 1;
}
+8  A: 

No, because this doesn't really make sense. Remember that a subclass contains all members of its parent class; therefore, B still has A's std::string key. Moreover, since B's std::string key is the same type, it's absolutely identical to A's - so what was the point of overriding it?

Also, note that during construction, when we're running A's constructor, B's virtual methods won't be called. This means that if we access key during A's construction, we'd get A's key - but then when B is constructed, that key would be shadowed, its data completely inaccessible.

That said, if you really do want to do something like this, for some reason, you'll need to use a virtual accessor function:

class A {
    private:
    std::string m_key;
    public:
    virtual std::string &key() { return m_key; }
    virtual const std::string &key() const { return m_key; }
};

class B : public A {
    private:
    std::string m_key;
    public:
    virtual std::string &key() { return m_key; }
    virtual const std::string &key() const { return m_key; }
};

int main()
{
    B b;
    b.key() = "Foo";
    return 0;
}
bdonlan
A: 

Class methods are code. Code is constant. Each particular class method has a pre-determined fixed behavior defined at compile time that can't be changed at run time. For this reason, in order to have polymorphic classes, we have to write many different versions of different methods in advance (i.e. at compile time), and then "attach" a specific set of those versions to class instances at run time, thus forming the specific run time behavior of each instance.

With data members the situation is completely different. Data members are not fixed. They are changeable. They hold values and these values can be freely changed at run time. This alone makes data members inherently "virtual" by themselves. You don't need to introduce an different "version" of data member in derived class. Instead, you just have to put a different value into an already existing data member. That alone is already analogous to the "virtuality" of the class methods. Moreover, this "data virtuality" is even more flexible than "virtuality" of the methods, because with data members you are not limited to a pre-determined set of values.

What your are proposing though looks like a higher degree of "virtuality": not only the value of data member is changeable, but the data member itself is overridable. (Call it meta-virtuality, or super-virtuality or double-virtualty.) But what would be the point, the benefit, the use-case of having this feature? I personally don't see it right away and your code sample isn't exactly telling.

AndreyT
A: 

I am also not entirely sure of your wording, you may be seeking:

#include <string>

template < typename T >
class A {
public:
    T key;
};

int main()
{
    typedef A<std::string> AString;
    AString a;
    a.key = "Foo";
    return 1;
}
Justin