用继承的类实现继承的抽象(纯虚拟)类?

时间:2015-07-17 12:44:09

标签: c++ inheritance abstract multiple-inheritance

我目前正在制作一个小型游戏引擎,并且遇到了一个我没想到的问题。

我有一个根类,我的引擎中的大多数类派生自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;
}

2 个答案:

答案 0 :(得分:5)

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

Get-ChildItem ...
<skipped>
} | Select Path,Size,Count | Out-File "files.txt"

您认为这是您的等级制度:

enter image description here

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

enter image description here

这应该说明问题。您的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 })。通过B的路径没有覆盖C,因此foo()仍被视为抽象。

将结构实际制作为钻石的方法是使用virtual inheritance

D

这样只有一个基类struct B : virtual A { void foo() override { } }; struct C : virtual A { virtual void bar() = 0; }; struct D : B, C { void bar() override { } }; 类,因此只有一个虚拟A,因此foo()中的覆盖就足够了。

答案 1 :(得分:3)

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

你应该阅读&#34;虚拟继承&#34;这将允许您只有一个CPObjectProtocol副本。

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