Polymorphic object members

房东的猫 提交于 2019-12-31 02:57:28

问题


I have the following problem. I have a base class and several classes inheriting from it. All those classes are sharing a very similar interface and will most probably not be required to overload most of the shared methods.

However, all of them are using different member objects that are derived from each other and share a very similar interface too.

class BaseClass
{
    protected:
        Com* com;

    public:
        void setReady()
        {
            com->setReady();
        }
}

class DerivedClass : BaseClass
{
    protected:
        DerivedCom* com;
}

class Derived2Class : BaseClass
{
    protected:
        Derived2Com* com;
}

How can I enable DerivedClass to have setReady() run its version of com instead of the one inherited from BaseClass?


回答1:


Construct your instances with different implementations of Com. (Assuming DerivedCom implements Com)

class BaseClass
{
    protected:
        Com* com;

    public:
        BaseClass(Com* c = new Com) : com(c) 
        {}

        void setReady()
        {
            com->setReady();
        }
}

class DerivedClass : BaseClass
{
    public:
        DerivedClass() : BaseClass(new DerivedCom) 
        {}
}

class Derived2Class : BaseClass
{
    public:
        Derived2Class() : BaseClass(new Derived2Com) 
        {}
}



回答2:


A simple solution is to introduce a getCom() protected virtual function, that returns a Com* or Com&:

virtual Com* getCom()
{ return this->com; }

The child classes can override it and return their own Com-derived instance. Your setReady() function can then be implemented as:

void setReady()
{
    getCom()->setReady();
}

Your com member can then be made private, btw.

The drawback with this solution is that you'll have multiple Com-derived instances in the child classes.




回答3:


Maybe a class template might help you:

class BaseClass
{
protected:
    Com* com;

public:
    virtual void setReady()
    {
        com->setReady();
    }
};

template<typename T>
class ComDerived : public BaseClass {
protected:
    T* com;
public:
    void setReady()
    {
        com->setReady();
    }
};

class DerivedClass : public ComDerived<DerivedCom>
{

};

class Derived2Class : public ComDerived<Derived2Com>
{

};



回答4:


Why not templated mother class?

template <typename T>
class BaseClass
{
    protected:
        T* com;

    public:
        void setReady()
        {
            com->setReady();
        }
};

class DerivedClass : BaseClass<DerivedCom>
{
};

class Derived2Class : BaseClass<Derived2Com>
{
};



回答5:


To build on d909b's answer, I'd do something like:

class BaseClass {
private:
   virtual Com * alloc_com() {
      return new Com;
   }
   Com * com;
public:
   BaseClass() : com(alloc_com()) {}
   void setReady() {
      com->setReady();
   }
};

class DerivedClass {
private:
   virtual Com * alloc_com() override {
      return new DerivedCom;
   }
};

class Derived2Class {
private:
   virtual Com * alloc_com() override {
      return new Derived2Com;
   }
};

This works as long as DerivedCom publicly inherits from Com AND when Com has a virtual destructor. If Com does not have a virtual destructor, you also need to have a virtual dealloc_com function. Otherwise, you need to use a template or CRTP pattern, and then you're limited to cases where you are able to deduce the type of the object at compile time. If you know these are your only cases though, using templates will allow you to use the interface without adding virtual function call overhead.



来源:https://stackoverflow.com/questions/13454756/polymorphic-object-members

标签
易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!