Why does it make sense to give definition for a pu

2019-02-05 19:34发布

Scott said on Effective C++, 3rd Edition, pg. 43 that to make an abstract class, we just need to give it a pure virtual destructor:

class AWOV {                  // AWOV = "Abstract w/o Virtuals"
public:
  virtual ~AWOV() = 0;        // declare pure virtual destructor
};

Then, he went on said that there is one twist: we must provide a definition for the pure virtual destructor:

AWOV::~AWOW() {}              // definition of pure virtual dtor

My question is, by specifiying = 0, for pure virtual functions, we are saying that the function cannot have any definition for the class where this pure virtual function is declared.

Why is it OK to provide a definition (even it is empty) for the pure virtual destructor here?

5条回答
Explosion°爆炸
2楼-- · 2019-02-05 20:12

Making it pure forces derived (non-abstract) classes to implement their own.

Providing an implementation allows derived classes to invoke base class behavior (which destructors do by default).

查看更多
再贱就再见
3楼-- · 2019-02-05 20:12

This is not necessary for all pure virtual functions. Not at all.

This way, the derived classes will still be forced to override the implementation, but there will be a default implementation in the base class, in case you need to call it. And that's the case here - because you're dealing with a destructor: when a derived object is being destroyed, its destructor is called and its base classes destructors are called as well. That's why you need an implementation for A::~A.

查看更多
地球回转人心会变
4楼-- · 2019-02-05 20:14

"we are saying that the function cannot have any definition for the class where this pure virtual function is declared."

That's not what pure virtual means. Pure virtual only means that the containing class cannot be instantiated (is abstract), so it has to be subclassed, and subclasses must override the method. E.g.,

struct A {
    virtual ~A() = 0;
};

A::~A() {}

struct B : A {};

int main()
{
    A a;  // error
    B b;  // ok
}

Here, the B destructor is implicitly defined. If it was another method that is pure virtual, you'd have to explicitly override it:

struct A {
    virtual void foo() = 0;
};

void A::foo() {}

struct B : A {};

int main()
{
    B b;  // error
}

Providing a definition for a pure virtual method is desirable when the base class must be abstract but still provide some default behavior.

In the specific case of a destructor, it has to be provided because it will be called automatically when subclass instances are destroyed. A program that tries to instantiate a subclass of a class with a pure virtual destructor without a definition will not pass the linker.

查看更多
5楼-- · 2019-02-05 20:14

There are 2 cases.

Pure virtual destructor

This case is specifically treated by the standard.

12.4 Destructors [class.dtor]

9) A destructor can be declared virtual (10.3) or pure virtual (10.4); if any objects of that class or any derived class are created in the program, the destructor shall be defined. If a class has a base class with a virtual destructor, its destructor (whether user- or implicitly-declared) is virtual.

The case of the destructor is different because all destructors are called in an inheritance hierearchy (assuming correct deletion) in reverse order of construction, even if not explicitly. So the base class destructor is called when the object gets deleted - that's why it needs an implementation.

Pure virtual method

These differ from destructors in that they're not required to be implemented, nor do they need an implementation. The difference for the missing requirement is that when a Derived::foo() gets called, it doesn't automatically call Base::foo() (not that it could, since it can or can not be implemented).

Why you would want to implement a pure virtual method depends on the case. I look at the pure specifier as a hint to the programmer, as opposed to related to the logic. It tells you - the programmer - that you should implement that method. It doesn't really matter if the base class has an implementation or not.

by specifiying = 0, for pure virtual functions, we are saying that the function cannot have any definition for the class where this pure virtual function is declared.

Not really. You're saying derived non-abstract classes have to override that function. This doesn't prevent you from implementing it yourself.

查看更多
【Aperson】
6楼-- · 2019-02-05 20:25

By making a function pure virtual we force the user of the class to replace the function with another in the derived class.

The base class function can still be called with BaseClass::myfunction(...)

Now the base class might want to provide some core functionality that the derived class may use if it chooses to do so.

查看更多
登录 后发表回答