问题
Is it good practice (and is it possible) to create an abstract class using only a pure virtual destructor in the parent class?
Here's a sample
class AbstractBase {
public:
AbstractBase () {}
virtual ~AbstractBase () = 0;
};
class Derived : public AbstractBase {
public:
Derived() {}
virtual ~Derived() {}
};
Otherwise how can I create an abstract class if the attributes and constructors of the derivatives class are all the same while the other method are totally different?
回答1:
Having only a pure virtual destructor in the base class is rarely a good practice, but it is possible and, in certain cases, even desirable.
For instance, if you rely on RTTI to dispatch messages to a subclass object by attempting a dynamic_cast on the pointer to the base class, you may need no methods in the base class except the destructor. In this case, make the destructor public virtual.
Since you have no other virtual methods except the destructor, you have to make it pure in order to prevent the creation of the objects of the base class.
Here, it is crucial to provide the empty body to that destructor (even though it is "=0"!)
struct AbstractBase {
virtual ~AbstractBase() = 0;
}
AbstractBase::~AbstractBase() {
}
Having the body allows the creation of subclass objects (provided that the subclass defines the destructor and does not set it as pure).
回答2:
An interface in C++ SHOULD have an a virtual destructor that is implemented and does nothing. All the other methods in the interface have be defined as abstract (e.g. adding = 0 in the declaration). This will ensure that you will not be able to create an instance of your interface class, but you can delete your object once you have assigned your interface pointer to the parent object. Sorry for bad wording, below is some code:
class ISampleInterface
{
public:
virtual ~ISampleInterface() { };
virtual void Method1() = 0;
virtual void Method2() = 0;
}
class SampleClass : public ISampleInterface
{
public:
SampleClass() { };
void Method1() { };
void Method2() { };
}
int main()
{
ISampleInterface *pObject = (ISampleInterface*)new SampleClass();
delete pObject;
return 0;
}
回答3:
This question reminds me of an Old New Thing post:
A customer asked for advice on how to accomplish something ... And I wasn't convinced that it was a good idea, sort of like asking for advice on how to catch a baseball in your teeth or pick all the cheese off your cheeseburger.
I explained several of the pitfalls of their approach ... and I concluded with the sentence, "This idea is fraught with peril, and I fear that my answers to your questions will be interpreted as approval rather than reluctant assistance."
You can create an abstract base class with only a virtual
destructor. I'm not sure why you would want to. Knowing that an object derives from a type, say Foo
, should mean I know what I can do with that object. In this case, I would only know that I could destroy the object, which isn't useful information.
But you are correct that the most obvious approach won't compile:
struct Foo {
virtual ~Foo() = 0;
};
struct Bar : Foo {
~Bar() { }
};
struct Baz : Foo {
~Baz() override { } // C++11
};
When I try to compile this, I get a link error because, while Bar::~Bar()
and Baz::~Baz()
are defined, Foo::~Foo()
is not, and the compiler wants to call Foo::~Foo()
whenever a Bar
or a Baz
is destroyed.
There are two solutions. The first is that virtual
functions don't have to be pure virtual:
struct Foo {
virtual ~Foo() { }
};
struct Bar : Foo {
~Bar() { }
};
struct Baz : Foo {
~Baz() override { } // C++11
};
struct Quux : Foo { };
But you specifically asked for a pure virtual destructor. And the answer is certainly weird: pure virtual functions can be defined by the class that declares them pure virtual:
struct Foo {
virtual ~Foo() = 0;
};
Foo::~Foo() { }
struct Bar : Foo {
~Bar() { }
};
struct Baz : Foo {
~Baz() override { } // C++11
};
struct Quux : Foo { };
The fact that you can do this doesn't mean it's a good idea. It's very unusual that you will want to declare a function pure virtual while defining the function. It might come up, but it will be very rare.
Otherwise how can I create an abstract class if the attributes and constructors of the derivatives class are all the same while the other method are totally different?
I think what really bothers me is that most advice nowadays is to use pure virtual functions to create something like Java interfaces. When you do that, you declare the methods that derived classes need to support, but leave leave those classes free to use whatever data members make sense. You're planning to declare only what data members types must contain, and leave the types free to have wildly different methods for the data. That seems like a bad idea.
来源:https://stackoverflow.com/questions/24316700/c-abstract-class-destructor