多态对象成员

时间:2012-11-19 13:26:24

标签: c++ polymorphism

我有以下问题。我有一个基类和几个继承自它的类。所有这些类都共享一个非常相似的接口,很可能不需要重载大多数共享方法。

但是,所有这些都使用了彼此派生的不同成员对象,并且共享一个非常相似的界面。

class BaseClass
{
    protected:
        Com* com;

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

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

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

如何让DerivedClasssetReady()运行其com版本,而不是从BaseClass继承的版本?

5 个答案:

答案 0 :(得分:4)

使用Com的不同实现构造您的实例。 (假设DerivedCom实现了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) 
        {}
}

答案 1 :(得分:2)

一个简单的解决方案是引入一个getCom()受保护的虚拟函数,该函数返回Com*Com&

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

子类可以覆盖它并返回它们自己的Com派生实例。然后,您的setReady()函数可以实现为:

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

然后您的com会员可以private,顺便说一句。

此解决方案的缺点是您将在子类中拥有多个Com派生的实例。

答案 2 :(得分:1)

也许类模板可能对您有所帮助:

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>
{

};

答案 3 :(得分:0)

为什么不模仿母亲班?

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

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

class DerivedClass : BaseClass<DerivedCom>
{
};

class Derived2Class : BaseClass<Derived2Com>
{
};

答案 4 :(得分:0)

基于d909b的答案,我会做类似的事情:

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;
   }
};

只要DerivedCom公开继承Com Com并且Com具有虚拟析构函数,这就有效。如果Com没有虚拟析构函数,则还需要具有虚拟dealloc_com函数。否则,您需要使用模板或CRTP模式,然后您将局限于能够在编译时推断出对象类型的情况。如果你知道这些是你唯一的例子,使用模板将允许你使用界面而不增加虚函数调用开销。