views:

983

answers:

5

I have a class with a member m_preferences (a vector containing assocation between word and features).

In this class the m_preferences is not static and thus any instance of the class has its specific m_preferences.

class Base{

private:

    Preferences m_preferences;

public:
...

}

I then created a derived class where m_preferences become static because I wanted that each new instance of this class share the same data for preferences no matter what happens.

class Derived: public Base{

private:

    static Preferences m_preferences;

public:
...

}

I got a linking error.

Is it possible to do what I want to do (transforming a non-static member into a static one through inheritance)?

If not what are the philosophy behind this impossibility? Was it planned?

Thank you,

Sincerely,

Ronan

+1  A: 

Yes, it is by design you cannot change the signature of a member while inheriting it.

Ali Shafai
+6  A: 

You can't stop every instance of Base - including every instance of Derived - from having a per-instance Preferences member variable as this is guaranteed by the definition of the Base class.

What you have done is added a new static Preferences member to the Derived class, which means that as well as a per-instance Preferences member associated with the base class you also have a global Preferences instance shared between all the Derived instances.

Because you have used the same name for these two members, in the context of a Parent member function, using the indentifier m_preferences will refer to the global shared instances unless you qualify it as in Base::m_preferences.

Your link error is probably because you need to provide a definition of Derived::m_preferences in one of your translation units.

e.g. in some.cpp, outside of any function bodies:

Preferences Derived::m_preferences;
Charles Bailey
+4  A: 

If I'm reading you right, you want to define a hierarchy of objects which will have either a static, or an individual, instance variable Preferences. Try this?

class Base
{
  virtual ~Base();
  virtual Preferences& MyPreferences() =0;
};

class DerivedA: public Base
{
public:
  virtual ~DerivedA();
  virtual Preferences& MyPreferences() { return m_preferences; }

private:
  Preferences m_preferences;
};

class DerivedB: public Base
{
public:
  virtual ~DerivedB();
  virtual Preferences& MyPreferences() { return preferences; }

private:
  static Preferences preferences;
};

Preferences DerivedB::preferences;

"Transforming", as Ali Shafai said it too, is not possible. The problem here is that "static" members are properties of the class itself rather than of individual objects, while virtual declarations and inheritance are about handling individual objects that may not be of the same class, uniformly, at a higher level of abstraction.

iCE-9
+4  A: 

Short answer: you aren't using inheritance properly.

Long answer: You defined Base as being a type with individual Preferences. If Derived does not meet the "is-a" qualification (Derived is a type that also has per-instance preferences), than it should not inherit from Base.

Perhaps a better design (?):

class NotDerivedAnymore
{

private:

    static Base m_base;

public:
...

}
rlbond
+1  A: 

You are breaking the is-a rule of inheritance.

You are stating that Base is a type that has its own Preferences member, and you are stating that Derived is a Base.

It appears that your Base and Derived objects share some qualities, but not as a direct inheritance

I believe this well get the result you want

class TrueBase{ 
    // Put data and functionality here that really is common for both types.
  private:

    virtual Preferences& get_preferences() = 0;
};

class Base : public TrueBase{
  private:

    virtual Preferences& get_preferences()
    {
        return m_preferences;
    }

    Preferences m_preferences;
};


class Derived: public TrueBase{  
  private:

    virtual Preferences& get_preferences()
    {
        return m_preferences;
    }

    static Preferences m_preferences;   
};
Shmoopty