Doesn't putting a "virtual destructor inside an interface" make it, by definition, not an interface anymore?
Asked Answered
S

4

26

So here is the box I am in. I want to understand why it is important to have a "virtual destructor inside your interface class". You will see why that stuff is in quotes if you can hang to the end... I also want to get all the vocabulary absolutely correct. Here is where I am at with the process so far:

  1. Sometimes you have base classes, sometimes you have derived classes which inherit from base classes.

  2. If you have a base-pointer that finds itself pointing to a derived-object, and further you want a member function call made from that base-pointer-pointing-to-a-derived-object to behave as if it had actually been called from the derived object, then the member function you call had better be declared virtual in the base class.

  3. An interface is any class with only pure virtual functions. If you derive a new class from this interface class and implement all the pure virtual functions, then you can finally create an instance of the derived class.

  4. You can never have an instance of an interface class, BUT you can have an instance of a pointer-to-interface-class.

  5. In the case where you have a pointer-to-interface-class that actually points to an object of the derived class (actually, I guess it would always have to if #4 is correct), and if you decide to delete that object through your pointer, then if you don't have a "virtual destructor inside your interface class", your intention to destroy the derived object will only be executed as a call to destroy the base object (i.e. the interface class) and since there is no virtual destructor, things won't ever get to the point where the destructor for the derived object is actually called -- thus causing memory leaks.

Phew. Okay, if that sounds right, onto my question. Is it enough just to declare a virtual destructor inside your interface like this:

virtual ~iFace();

That looks wrong to me... so what happens if you make the destructor pure virtual like this:

virtual ~iFace() = 0;

Since they are just declarations, do either of these count for being a "virtual destructor inside your interface class"? Can you even have a declared but un-defined destructor? Only if it is pure virtual I would guess...

Anyway, so getting back to the title question... I really am going as fast as I can... Here is the money shot... If your "virtual destructor inside your interface class" requires at least an empty definition like this:

virtual ~iFace() {};

Then that member function is not pure virtual (can't be because you gave it a definition) and therefore your class is no longer an interface (it does not only contain pure virtual member functions).

This would imply that if you define a virtual destructor for your interface, then you no longer have an interface (but just some abstract base class). Is this just an abuse of language? Do I understand what is going on?

note: All this came from asking myself "What is an interface?" and then reading this question's answers: How do you declare an interface in C++?

Hope that wasn't too long a walk for too short a ride, but I am determined to completely understand these concepts and their associated vocabulary.

Superheterodyne answered 6/8, 2011 at 13:9 Comment(7)
The concept of an interface is important enough to inspire language extensions. Review this page: msdn.microsoft.com/en-us/library/4bt10hsa%28VS.80%29.aspxDeracinate
Wow, what a bunch of good answers!Superheterodyne
Interfaces in C++ are just concepts. Just because you have an implementation of some functions it does not stop it being an interface (its just not pure as in the mathematical sense). The real world is a dirty grimy place and not everything fits beautifully into mathematical concepts. Just go with the flow. PS. All classes also have a couple of compiler defined methods associated with them so none are ever going to be pure. PPS. I hate the Java enforcement of pure interfaces (sometimes it would make the code simpler to have helper methods defined).Duval
"In fact, a class with only pure virtual functions is often called an interface." -- Bjarne S. ... I guess I missed the word 'often'... DANG IT!! www2.research.att.com/~bs/bs_faq2.htmlSuperheterodyne
I'm a .net person rather than a C++ person, but I would think that the defining concept for an interface would not be that it has only pure virtual functions, but rather that it has no member fields. If an class has a pure virtual method SetBounds(int left, int top, int width, int height, int args_specified) and non-virtual wrapper methods like SetWidth(int width) which would call it appropriately, I wouldn't think the non-virtual methods would make it not an "interface". I know .net interfaces would require extension methods for that, but I consider that a platform limitation.Situated
@LokiAstari, it sounds like you might be confusing two concepts of pure in computing, one being pure as in not having an implementation (as in C++), the other being pure as in not having any side-effects (as in functional programming), which you seem to be alluding to by invoking purity "as in the mathematical sense", which is where the purity of functional programming is oriented to.Abbieabbot
Why would you care what "interface" means? Why do you want a class to be an "interface"?Engleman
D
28

Why Abstract class destructor should be virtual and have a definition?

Calling delete on a polymorphic Base class pointer pointing to a Derived class object & the Base class not having a virtual destructor causes an Undefined Behavior.

So you do need to declare the destructor of the polymorphic Base class as virtual. Once you declare your destructor explicitly virtual, you do need to provide a definition for it. This is because the compiler by default generates(defines) a destructor for every class but if you explicitly declare the destructor then the compiler does not do so and leaves it for you to provide a definition for your own destuctor. It makes sense because the compiler sees explicit declaration as an indication that you want to do some non trivial operations(even if you are not in need of doing so) in the destructor and it provides you the opportunity to do so by forcing you to give the definition.


Myth 1:
There is something called an Interface in C++.

NO
C++ as a language does not provide an Interface What you refer to as Interface is called an Abstract class in C++. Abstract Classes are used to simulate the behavior of Interface in C++.

What is an Abstract class?
By definition an abstract class should have at least one pure virtual function.


Myth 2:
All functions inside Abstract class need to be pure virtual.

NO
Abstract classes do not require all functions inside them to be pure virtual. An object of an Abstract cannot be created if it has at least one pure virtual function. Though, as you correctly mentioned you can create pointers to it.


Myth 3:
Pure virtual functions cannot have a definition.

NO
It is perfectly valid for Pure virtual functions to have a definition.


Why would I ever need a Pure virtual function with definition?
Code speaks louder then words, So here is a simple example:
Warning: Uncompiled code only for demonstration

class IMyInterface
{
    int i;
    int j;
    public:
        virtual void SetMembers(int ii, int jj)=0;
};

/*The pure virtual function cannot be inline in the class definition*/
/*So this has to be here*/
void IMyInterface::SetMembers(int ii, int jj)
{
    i = ii;
    j = jj;
}

class Myclass: public IMyInterface
{
    int k;
    int l;
    public:
        virtual void SetMembers(int ll, int m, int a, int b)
        {
             k = ll;
             l = m;
             IMyInterface::SetMembers(a,b);
         }
};

int main()
{

    MyClass obj;
    obj.SetMembers(10,20,30,40);
    return 0;
}
Duer answered 6/8, 2011 at 13:14 Comment(7)
I'd just add that since there is no syntax to add a body to pure virtual member function declarations, these must be defined outside the class definition.Yevetteyew
@Nicola Musatti: Agreed, I distinctly remember there was a Language Lawyer Q about why pure virtual functions cannot have inline definition by Armen.Duer
@Als: I understand that ABCs have at least one virtual function ... one thing that hung me up was reading "an equivalent of an interface would be an abstract base class without any data with only pure virtual functions" from that other question I referenced. Dang it. As for myth #3, why would you ever want a definition for a pure virtual member function? I don't know, but I'm sure the answer to this is equally awesome :) Thanks!Superheterodyne
@Jimmy: Check the updated answer, hope that simple example answers your query about Myth #3 :)Duer
@Als: "This is very occasionally useful (to provide some simple common implementation detail for derived classes)." -- Bjarne (www2.research.att.com/~bs/bs_faq2.html) I can't decide what I like better, the way you showed it with constructors, or the use of the phrase "very occasionally"... in any case, you guys are killing it!Superheterodyne
@Als: one last thing, I just read that a pure virtual that gets defined in the base class must still be overridden in the derived class to be able to use it... for your example, does that mean just a declaration in the derived class or actually repeating the base's function's definition?Superheterodyne
@Jimmy: Unless you override a virtual function in derived class, You will always end up calling the function in the Base class because virtual functions are hierarchical So to be able to call derived class version of the function polymorphically, you should override it and provide a definition in derived class.Duer
T
10

C++ doesn't have a native interface entity. Interfaces are implemented as regular classes.

What makes a class an interface in C++ is, therefore, not something that has universal agreement. Personally I consider a class to be an interface if it has no data members, no user-declared constructors and all of its functions are pure virtual - with the possible exception of its destructor - and all of its base classes, if any, are also interfaces. If a class doesn't quite fit all of these properties I might refer to it as a "fat" interface (generally not a compliment!).

If you want to delete dynamically allocated polymorphic classes through a pointer to a base class (such as an "interface" class) then the base class destructor must be declared virtual. This means that it must be a user-declared destructor and not an implicitly declared destructor which would be non-virtual.

Once you declare a destructor explicitly, you must provide an implementation for it. (A base class destructor will always be used when you destroy an instance of any class derived from it whether or not the base class destructor is declared pure virtual, virtual or non-virtual.) This is purely an C++ language implementation detail. It doesn't mean that your base class is any less of an "interface", if you have an interface class then it is very likely that the implementation of the destructor will be empty in any case - you have no members or base classes with members to worry about.

If your interface has at least some pure virtual functions then there is no real merit to marking the destructor as pure, your interface class is already an abstract class. Derived class destructors don't technically override base class destructors so you're not requiring derived classes to provide user-declared destructors or anything like that.

Declaring a destructor as a pure virtual also robs you of the ability to provide the definition of the destructor inline in the class definition, although this is a minor detail.

Tb answered 6/8, 2011 at 13:27 Comment(1)
"no constructors" - no user-defined constructors ;-pCongresswoman
P
7

"An interface is any class with only pure virtual functions"

-- The concept in C++ is called abstract class. An abstract class is a class with at least one pure virtual function. It doesn't require that all of its member functions are pure virtual though. You cannot instantiate any abstract class.

"This would imply that if you define a virtual destructor for your interface, then you no longer have an interface (but just some abstract base class). Is this just an abuse of language? Do I understand what is going on?"

-- On the contrary, you must provide a definition for the destructor even if it is pure virtual because destructors are always called in a down-up manner in inheritance hierarchy.

Standard 12.4:

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.

Example:

class A
{
public:
   // this is stil a pure virtual function
   // when there is a definition
   virtual ~A() = 0;
};

class B: public A
{};

int main()
{
   // fail to link due to missing definition of A::~A()
   B b;
}
Preceptive answered 6/8, 2011 at 13:18 Comment(0)
Y
2
  1. OK.
  2. OK; if the member function is not declared virtual in the base class, the one from the base class is called; if the member function is neither defined nor declared pure virtual in the base class, you get an error.
  3. In C++ you don't have interfaces as you have in Java and C#; abstract base classes in C++ combine interfaces and abstract classes as they are present in the latter two languages. A C++ class is abstract if it has at least one pure virtual member function.
  4. Replace interface with abstract class.
  5. Formally you cannot make assumptions on what happens if you delete a derived class from a pointer to a base class if the base class's destructor is not declared virtual.

Given all this, in general your abstract base class will already have some pure virtual member function which ensure that it won't be possible to instantiate it, so the usual way of doing things is to define an inline virtual destructor that does nothing.

Yevetteyew answered 6/8, 2011 at 13:31 Comment(0)

© 2022 - 2024 — McMap. All rights reserved.