2

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

但是,它们都使用不同的成员对象,这些成员对象相互派生,并且也共享一个非常相似的接口。

class BaseClass
{
    protected:
        Com* com;

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

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

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

如何启用DerivedClass运行setReady()其版本com而不是继承自的版本BaseClass

4

5 回答 5

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) 
        {}
}
于 2012-11-19T13:34:11.567 回答
2

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

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

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

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

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

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

于 2012-11-19T13:31:48.927 回答
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>
{

};
于 2012-11-19T13:29:39.557 回答
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 没有虚拟析构函数,还需要有一个虚拟的 dealloc_com 函数。否则,您需要使用模板或 CRTP 模式,然后您仅限于能够在编译时推断出对象类型的情况。但是,如果您知道这些是您唯一的情况,那么使用模板将允许您在不增加虚函数调用开销的情况下使用接口。

于 2012-11-19T14:07:04.090 回答
0

为什么不模板化母班?

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

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

class DerivedClass : BaseClass<DerivedCom>
{
};

class Derived2Class : BaseClass<Derived2Com>
{
};
于 2012-11-19T13:30:12.437 回答