开发者

Abstract class without abstract methods

开发者 https://www.devze.com 2023-02-15 14:50 出处:网络
Is it possible to make a class abstract in C++ without declaring any abstract methods? Currently, I have a Sprite class with a StaticSprite and DynamicSprite subclass. I would like to make the Sprite

Is it possible to make a class abstract in C++ without declaring any abstract methods? Currently, I have a Sprite class with a StaticSprite and DynamicSprite subclass. I would like to make the Sprite class abstract.

T开发者_如何学运维he problem is that there aren't any methods they share. Well, both StaticSprite and DynamicSprite might share a draw()-method, but the parameters of this method are different so this isn't an option.

Thank you!

EDIT: Here is the code to demonstrate what I'm trying to do:

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);
};

As you see, it's useless to create a Sprite-object, so I would like to make that class abstract. But I can't make draw() abstract as it uses different parameters.


You can declare your destructor as pure virtual, since all classes have one.

class AbstractClass
{
public:
    virtual ~AbstractClass() = 0 ;
} ;

However, you will need to define this destructor elsewhere.

AbstractClass::~AbstractClass() {}


If the class does nothing and provides nothing, and only exists as a marker, there's no reason to worry about whether or not it's abstract. This is essentially a non-issue.

If you absolutely wish to ensure that one is never instantiated except in the context of inheritance, use protected constructors.

Please avoid making a pure virtual destructor. That way madness lies.


No there isn't.

You could use this of course:

class Sprite
{
};

but of course the compiler isn't going to complain when you try to create an instance of it.

You may add a pure virtual destructor:

class Sprite
{
public:
    virtual ~Sprite () = 0;
};

or you may make the constructor protected, stopping the instantiation:

class Sprite
{
protected:
    Sprite ();
};


For the specific circumstances of your post, consider private inheritance. That way you get to lazily use the implementation of the base, without advertising a spurious IS-A relationship to the world.


The traditional way of doing this is to make a pure virtual destructor, then implement it.

// .h
struct Foo {
  virtual ~Foo() = 0;
};

// .cpp
Foo::~Foo() {
}


The problem is that there aren't any methods they share.

Well there's your problem right there. You shouldn't be using inheritance here! If you aren't intending to substitute one class for the other they just shouldn't be in a parent-child relationship.

Depending on the needs they should be totally unrelated, templates, or use composition.

EDIT: Based on the code sample, you're inheriting to reuse and I would suggest using composition instead. Sprite could be a struct that is owned by both DynamicSprite and StaticSprite. You can put as much/little helper logic into Sprite as appropriate.


The best approach is to protect the class constructors, this way the class cannot be instantiated directly and therefore it's essentially abstract:

class SomeBaseClass 
{
protected:
    SomeBaseClass() {}
    SomeBaseClass(const SomeBaseClass &) {}
    SomeBaseClass &operator=(const SomeBaseClass&) {}
public:
    virtual ~SomeBaseClass() {}
    ...
};

Or, newer style:

class SomeBaseClass 
{
protected:
    SomeBaseClass() = default;
    SomeBaseClass(const SomeBaseClass &) = delete;
    SomeBaseClass &operator=(const SomeBaseClass&) = delete;
public:
    virtual ~SomeBaseClass() = default;
    ...
};

Destructor is generally better to keep public because you might want to delete an object by its base class pointer.


To make a purely abstract class that cannot be instantiated without deriving from it - you must define at least one abstract method.

eg.

 virtual void blah() const = 0;

Otherwise you can use any class as an abstract class


If you really must use inheritance, consider using the non-virtual interface (NVI) idiom (see http://www.parashift.com/c++-faq-lite/strange-inheritance.html#faq-23.3)

Essentially the base class will define an overloaded, non-virtual set of methods, which call protected pure virtual functions from the derived classes.

What you definately don't want to do is overload a virtual function (which it looks like you really want to do).

0

精彩评论

暂无评论...
验证码 换一张
取 消