用继承的class实现继承的抽象(纯虚)class?
Fulfil inherited abstract (pure virtual) class with an inherited class?
我目前正在做一个小游戏引擎,刚遇到一个没想到的问题。
我有一个根 class,我引擎中的大多数 class 都来自 CPObject
。 CPObject
符合 CPObjectProtocol
,抽象 class 定义了一些纯虚函数。
我创建了另一个协议 TextureProtocol
及其具体实现 SDLTexture
,它也继承自 CPObject
。到目前为止,一切正常,我可以创建 SDLTexture 的实例。但是,如果我让 TextureProtocol
继承自 CPObjectProtocol
,clang 会告诉我无法创建抽象 class.
的实例
我假设 class 可以通过继承另一个 class 的实现来实现接口。我错了吗?
// 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;
}
你的SDLTexture同时继承自CPObject和TextureProtocol,每一个都继承自CPObjectProtocol,所以你在每个SDLTexture中有两个不同的CPObjectProtocol副本,第二个副本有一个指向缺少那些纯虚拟实现的虚表的指针函数。
您应该阅读有关 "virtual inheritance" 的内容,它将允许您只有一个 CPObjectProtocol 副本。
由于 CPObjectProtocol 没有数据,只有方法,显然您的意图是在每个 SDLTexture 中只拥有它的一个副本。
我将简化示例来演示问题。你有:
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 { }
};
这样只有一个base A
class,所以只有一个virtual foo()
,所以B
中的覆盖就足够了。
我目前正在做一个小游戏引擎,刚遇到一个没想到的问题。
我有一个根 class,我引擎中的大多数 class 都来自 CPObject
。 CPObject
符合 CPObjectProtocol
,抽象 class 定义了一些纯虚函数。
我创建了另一个协议 TextureProtocol
及其具体实现 SDLTexture
,它也继承自 CPObject
。到目前为止,一切正常,我可以创建 SDLTexture 的实例。但是,如果我让 TextureProtocol
继承自 CPObjectProtocol
,clang 会告诉我无法创建抽象 class.
我假设 class 可以通过继承另一个 class 的实现来实现接口。我错了吗?
// 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;
}
你的SDLTexture同时继承自CPObject和TextureProtocol,每一个都继承自CPObjectProtocol,所以你在每个SDLTexture中有两个不同的CPObjectProtocol副本,第二个副本有一个指向缺少那些纯虚拟实现的虚表的指针函数。
您应该阅读有关 "virtual inheritance" 的内容,它将允许您只有一个 CPObjectProtocol 副本。
由于 CPObjectProtocol 没有数据,只有方法,显然您的意图是在每个 SDLTexture 中只拥有它的一个副本。
我将简化示例来演示问题。你有:
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 { }
};
这样只有一个base A
class,所以只有一个virtual foo()
,所以B
中的覆盖就足够了。