是否可以在不声明任何抽象方法的情况下在C ++中创建类抽象?目前,我有一个带有StaticSprite和DynamicSprite子类的Sprite类。我想让Sprite类抽象化。
问题在于他们没有共享任何方法。好吧,StaticSprite和DynamicSprite都可以共享一个draw()方法,但是这个方法的参数是不同的,所以这不是一个选项。
谢谢!
编辑: 以下是演示我正在尝试做的代码:
的Sprite:
class Sprite
{
public:
Sprite(HINSTANCE hAppInst, int imageID, int maskID);
~Sprite();
protected:
HINSTANCE hAppInst;
HBITMAP hImage;
HBITMAP hMask;
BITMAP imageBM;
BITMAP maskBM;
HDC hSpriteDC;
};
Staticsprite:
class StaticSprite : public Sprite
{
public:
StaticSprite(HINSTANCE hAppInst, int imageID, int maskID);
~StaticSprite();
void draw(Position* pos, HDC hBackbufferDC);
};
Dynamicsprite:
class DynamicSprite : public Sprite
{
public:
DynamicSprite(HINSTANCE hAppInst, int imageID, int maskID);
~DynamicSprite();
void draw(HDC hBackbufferDC);
};
如你所见,创建一个Sprite对象是没用的,所以我想把这个类抽象化。但我不能使draw()抽象,因为它使用不同的参数。
答案 0 :(得分:15)
您可以将析构函数声明为纯虚拟,因为所有类都有一个。
class AbstractClass
{
public:
virtual ~AbstractClass() = 0 ;
} ;
但是,您需要在其他位置定义此析构函数。
AbstractClass::~AbstractClass() {}
答案 1 :(得分:13)
如果班级什么都不做,什么都不提供,只作为标记存在,那么就没有理由担心它是否是抽象的。这基本上不是问题。
如果您绝对希望确保从未实例化一个,除了在继承的上下文中,请使用protected constructors。
请避免使用纯虚拟析构函数。那种疯狂就是谎言。
答案 2 :(得分:3)
对于您帖子的具体情况,请考虑私有继承。这样你就可以懒惰地使用基础的实现,而不会向世界宣传虚假的IS-A关系。
答案 3 :(得分:2)
没有。
你当然可以使用这个:
class Sprite
{
};
但是当你尝试创建它的实例时,编译器当然不会抱怨。
您可以添加纯虚拟析构函数:
class Sprite
{
public:
virtual ~Sprite () = 0;
};
或者您可以使构造函数受到保护,停止实例化:
class Sprite
{
protected:
Sprite ();
};
答案 4 :(得分:2)
这样做的传统方法是创建一个纯虚拟析构函数,然后实现它。
// .h
struct Foo {
virtual ~Foo() = 0;
};
// .cpp
Foo::~Foo() {
}
答案 5 :(得分:2)
问题在于没有 他们分享的方法。
那里有你的问题。你不应该在这里使用继承!如果你不打算用另一个班代替另一个班,他们就不应该处于亲子关系中。
根据需要,它们应完全不相关,模板或使用构图。
编辑:根据代码示例,您继承重用,我建议使用组合。 Sprite
可以是struct
和DynamicSprite
所拥有的StaticSprite
。您可以根据需要将尽可能多的/辅助逻辑放入Sprite
。
答案 6 :(得分:1)
最好的方法是保护类构造函数,这样就不能直接实例化类,因此它本质上是抽象的:
class SomeBaseClass
{
protected:
SomeBaseClass() {}
SomeBaseClass(const SomeBaseClass &) {}
SomeBaseClass &operator=(const SomeBaseClass&) {}
public:
virtual ~SomeBaseClass() {}
...
};
或者,更新的风格:
class SomeBaseClass
{
protected:
SomeBaseClass() = default;
SomeBaseClass(const SomeBaseClass &) = delete;
SomeBaseClass &operator=(const SomeBaseClass&) = delete;
public:
virtual ~SomeBaseClass() = default;
...
};
析构函数通常更好地保持公共,因为您可能希望通过其基类指针删除对象。
答案 7 :(得分:0)
要创建一个纯粹的抽象类,如果不从中派生而无法实例化 - 您必须至少定义一个抽象方法。
例如
virtual void blah() const = 0;
否则,您可以将任何类用作抽象类
答案 8 :(得分:-1)
如果你真的必须使用继承,请考虑使用非虚拟接口(NVI)习语(参见http://www.parashift.com/c++-faq-lite/strange-inheritance.html#faq-23.3)
基本上,基类将定义一个重载的非虚拟方法集,它从派生类中调用受保护的纯虚函数。
你肯定不想做的是重载虚拟功能(看起来你真的想做)。