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

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

我有一个根类,我的引擎中的大多数类派生自CPObject. CPObject符合CPObjectProtocol,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;
}
最佳答案
我将简化示例来演示问题.你有:

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(),所以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中的覆盖就足够了.

转载注明原文:c – 使用继承类实现继承的抽象(纯虚拟)类? - 代码日志