Does C ++ create the standard "constructor / destructor / copy constructor / copy assignment operator" for a pure virtual class?

Compiled C ++ compilers generate default functions such as Constructor / Destructor / Copy-Constructor ... for this "class"?

class IMyInterface { virtual void MyInterfaceFunction() = 0; } 

I mean, it is not possible to instantiate this "class", so I think that no functions are generated by default. Otherwise, people say that you need to use a virtual destructor. This means that if I do not define a virtual destructor, it will be created by default, not virtual.

In addition, I want to know whether it is reasonable to define a virtual destructor for a clean virtual interface, for example, above? (Thus, there are no pointers or data here, so nothing needs to be destroyed)

Thanks.

+8
c ++ interface pure-virtual
source share
4 answers

In addition, I want to know whether it is reasonable to define a virtual destructor for a clean virtual interface, for example, above? (Thus, there are no pointers or data here, so nothing needs to be destroyed)

This is not only reasonable, recommended. This is due to the fact that in the case of virtual functional hierarchies (automatically) a call to the destructor of a specialized class also calls all the destructors of its base classes. If they are not defined, you should get a binding error.

If you define at least one virtual function in your class, you must also define a virtual destructor.

A destructor can be defined using =default , though:

Here is an example of a fixed (compiled) code:

 class ImyInterface { virtual void myInterfaceFunction() = 0; virtual ~ImyInterface() = 0; } ImyInterface::~ImyInterface() = default; 
+1
source share

Yes.

There is no wording that requires the class to be realistic, for these special member functions to be declared implicitly.

It makes sense. just because you cannot create an instance of the database does not mean that the Derived class does not want to use these functions.

 struct Base { virtual void foo() = 0; int x; }; struct Derived : Base { Derived() {}; // needs access to Base trivial implicit ctor virtual void foo() {} }; 

Cm:

  • & sect; 12.1 / 5 (ctor)
  • & sect; 12.8 / 9 (move)
  • & sect; 12.8 / 20 (copy)
+3
source share

In addition, I want to know whether it is reasonable to define a virtual destructor for a clean virtual interface, for example, above? (Thus, there are no pointers or data here, so nothing needs to be destroyed)

Will derived classes ever do anything in their destructors? Can you be sure that they will never be, even when someone else takes charge of the development?

The whole point of a virtual destructor is not to make sure that the base class is correctly destroyed, which will happen anyway. The fact is that the destructor of the derived class is called using the common interface:

 struct A { virtual ~A() {} virtual int f() = 0; }; class B : public A { std::ifstream fh; public: virtual ~B() {} virtual int f() { return 42; } }; std::shared_ptr<A> a = new B; 

When a goes out of scope, why does ifstream close? Because the destructor deletes the object using the virtual destructor.

+1
source share

This concerns the second question about declaring a virtual destructor for an abstract base class (for example, at least one member function is pure virtual). Here's a real-world example of the LLVM clang ++ compiler that catches a potential problem. This happened with the version of the command line tools provided by Apple Developer for Mac OS X Mavericks.

Suppose you have a set of derived classes that end up having a parent with an abstract base class to define a common interface. Then you need to have a storage container, such as a vector, that is intentionally declared to hold a pointer to an abstract base class for each element. Later, following good technical practice, the container elements should be โ€œdeletedโ€ and the memory returned to the heap. The easiest way to do this is to cross the vector element over the element and call the delete operation on each of them.

Well, if the abstract base class does not declare the destructor as virtual, the clang ++ compiler gives a friendly warning about calling a non-virtual destructor in an abstract class. Keep in mind that in fact, only derived classes are allocated from the heap using the new operator. The pointer type of the derived class from the inheritance relation is indeed an abstract type of the base class (for example, the is-a relation).

If the abstract destructor of the base class is not virtual, then how will the handle to the correct derived class be called to free memory? In the best case, the compiler knows better (at least potentially with C ++ 11) and makes this possible. If the -Wall option of the compiler is enabled, then a compilation warning should appear. However, in the worst case, the destructor of the derived class is never reached, and the memory is never returned to the heap. Therefore, a memory leak is currently occurring, which can be very difficult to track and repair. All that is required is a one-time addition of the "virtual" to the declaration of the destructor of the abstract base class.

Code example:

 class abstractBase { public: abstractBase() { }; ~abstractBase() { }; virtual int foo() = 0; }; class derived : abstractBase { public: derived() { }; ~derived() { }; int foo() override { return 42; } }; // // Later on, within a file like main.cpp . . . // (header file includes are assumed to be satisfied) // vector<abstractBase*> v; for (auto i = 0; i < 1000; i++) { v.push_back(new derived()); } // // do other stuff, logic, what not // // // heap is running low, release memory from vector v above // for (auto i = v.begin(); i < v.end(); i++) { delete (*i); // problem is right here, how to find the derived class' destructor? } 

To eliminate this potential memory leak, the abstract base class must declare its destructor virtual. Nothing more is required. Now the abstract base class becomes the following:

 class abstractBase { public: abstractBase() { }; virtual ~abstractBase() { }; // insert virtual right here virtual int foo() = 0; } 

Note that the abstract base class currently has empty constructor and destructor bodies. As stated in Lightness, the compiler creates a default constructor, a destructor, and a copy constructor for an abstract base class (if it is not defined by an engineer). It is strongly recommended that you check out any of the C ++ programming language editions by the C ++ creator, Bjarne Stroustrup, for more information on abstract base classes.

0
source share

All Articles