【问题标题】:Fulfil inherited abstract (pure virtual) class with an inherited class?用继承的类实现继承的抽象(纯虚拟)类?
【发布时间】:2015-07-17 12:44:08
【问题描述】:

我目前正在做一个小型游戏引擎,刚刚遇到了一个我没想到的问题。

我有一个根类,我的引擎中的大多数类都派生自 CPObjectCPObject 符合 CPObjectProtocol,一个定义了一些纯虚函数的抽象类。

我创建了另一个协议TextureProtocol,它的具体实现SDLTexture也继承自CPObject。到目前为止,一切正常,我可以创建 SDLTexture 的实例。但是,如果我让 TextureProtocol 继承自 CPObjectProtocol,clang 会告诉我无法创建抽象类的实例。

我假设一个类可以通过继承另一个类的实现来实现接口。我错了吗?

// CPObject abstract interface/protocol
class CPObjectProtocol {
public:

    virtual void retain() = 0;
    virtual void release() = 0;
    //more methods like this
};

// CPObject implementation.
class CPObject : public CPObjectProtocol {
public:

    CPObject() { _retainCount = 0; }
    virtual ~CPObject() { }

    // implementation of CPObjectProtocol
    virtual void retain() { _retain++; }
    virtual void release() {
        if(--_retainCount <= 0) {delete this;}
    }
private:
    int _retainCount;
};


// Texture absract interface/protocol
// inherits from CPObjectProtocol so that retain() and release()
// can be called on pointers to TextureProtocol (allowing for
// implementations to be swapped later)
class TextureProtocol : public CPObjectProtocol {

public:
    virtual Color getColor() = 0;
};

// An implementation of TextureProtocol
// I assumed it would fulfil CPObjectProtocol by inheriting
// from CPObject's implementation?
class SDLTexture : public CPObject, public TextureProtocol {
public:
    SDLTexture() { _id = 0; }
    virtual ~SDLTexture { }

    // implementation of TextureProtocol
    virtual int getID() { return _id; }

private:
    int _id;
}

【问题讨论】:

  • 请贴一些真实的代码。我得到了几十个语法错误,如果我全部修复它们,代码就会编译。无论如何,您还需要在CPObjectProtocol 中使用虚拟析构函数。

标签: c++ inheritance abstract multiple-inheritance


【解决方案1】:

我将简化示例来演示问题。你有:

struct A {
    virtual void foo() = 0;  
};

struct B : A {
    void foo() override { }  
};

struct C : A {
    virtual void bar() = 0;    
};

struct D : B, C {
    void bar() override { }  
};

你认为这是你的层次结构:

但实际上它看起来像这样:

这应该能说明问题。您的D 有两个名为foo 的纯虚函数(通过其A 基的both),其中只有一个具有覆盖(通过B)。通过C 的路径没有覆盖foo(),所以D 仍然被认为是抽象的。

真正将你的结构变成钻石的方法是使用virtual inheritance

struct B : virtual A {
    void foo() override { }  
};

struct C : virtual A {
    virtual void bar() = 0;    
};

struct D : B, C {
    void bar() override { }  
};

这种方式只有一个基类A,所以只有一个虚拟foo(),所以B中的覆盖就足够了。

【讨论】:

    【解决方案2】:

    您的 SDLTexture 继承自 CPObject 和 TextureProtocol,每个都继承自 CPObjectProtocol,因此您在每个 SDLTexture 中有两个不同的 CPObjectProtocol 副本,第二个副本有一个指向缺少这些纯虚函数实现的 vtable 的指针。

    您应该阅读“虚拟继承”,这将允许您只有一个 CPObjectProtocol 副本。

    由于 CPObjectProtocol 没有数据,只有方法,显然您的意图是在每个 SDLTexture 中只保留一个副本。

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 2014-08-16
      • 1970-01-01
      • 2012-10-11
      • 1970-01-01
      • 1970-01-01
      • 2014-04-20
      • 1970-01-01
      相关资源
      最近更新 更多