没有抽象方法的抽象类

时间:2011-03-07 21:38:41

标签: c++

是否可以在不声明任何抽象方法的情况下在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()抽象,因为它使用不同的参数。

9 个答案:

答案 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可以是structDynamicSprite所拥有的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

基本上,基类将定义一个重载的非虚拟方法集,它从派生类中调用受保护的纯虚函数。

你肯定不想做的是重载虚拟功能(看起来你真的想做)。