Developer forums (C::B DEVELOPMENT STRICTLY!) > Development

Building C::B with GCC 4.1.0

<< < (5/6) > >>

Michael:

--- Quote from: thomas on February 09, 2006, 10:07:39 pm ---I don't get the point with the virtual destructor, to me it seems wrong. But hey, don't bother, I am neither God nor Stroustrup, so I would not know :)

--- End quote ---

It seems that I have misunderstood the remark of the expert :). His explanation was may be a bit too short :roll:. After asking him again he told me:


--- Quote ---If you have a pure class, which has no virtual function, and you will likely _not_ to derive from this class: there is no reason to define a virtual destructor. You may still define a non-virtual destructor if you have to do some clean-up on the end of the object lifetime.

However if you create a class which is part of a class hierarchy, and you intend to derive other classes from this class, and even more if you plan to use this hierarchy in polymorphic way (i.e. calling virtual functions, etc...) it is a good design choice to create a virtual destructor, even if you have nothing to clean-up in the base class.

--- End quote ---

This seems to confirm what you have said.

Michael

thomas:
Allow me to come back to this off-topic one last time :lol:

Apparently, this virtual destructor thing is a wide-spread misconception because I encountered a couple of people in the past few days who told me the exact same thing ("yea, it's a good thing, I always do it..."). The last one only a few minutes ago.

Thus, to visualize how expensive unnecessary virtual functions can be, I wrote the following code:

--- Code: ---#include <stdio.h>

class Integer {int a;};

class VirtualFoo{public: virtual ~VirtualFoo(){};};

class VirtualInteger
{
    int a;
public:
    virtual void Empty(){};
};

class MultiVirtualInteger: public VirtualFoo, public VirtualInteger {};

int main()
{
    int a;
    Integer b;
    VirtualInteger c;
    MultiVirtualInteger ow;
    Integer d[50000];
    Integer e[50000];
    VirtualInteger f[50000];
    MultiVirtualInteger this_hurts[50000];

    printf("int:\t\t\t %d\n", sizeof(a));
    printf("Integer:\t\t %d\n", sizeof(b));
    printf("VirtualInteger:\t\t %d\n", sizeof(c));
    printf("MultiVirtualInteger:\t %d\n\n", sizeof(ow));
    printf("int[]:\t\t\t %d\n", sizeof(d));
    printf("Integer[]:\t\t %d\n", sizeof(e));
    printf("VirtualInteger[]:\t %d\n", sizeof(f));
    printf("MultiVirtualInteger[]:\t %d\n", sizeof(this_hurts));

    return 0;
}
--- End code ---
Please excuse the C/C++ mixture, I will probably never learn to use streams :P

The program outputs the following on a "typical" 32 bit machine:

--- Code: ---int:                     4
Integer:                 4
VirtualInteger:          8
MultiVirtualInteger:     12

int[]:                   200000
Integer[]:               200000
VirtualInteger[]:        400000
MultiVirtualInteger[]:   600000

Press any key to continue.
--- End code ---
As can be seen, it costs nothing to encapsulate an integer into a class (I left out accessors, so it is not really useful, but let's not be picky). Contrarily, having virtual functions (even if it's just the empty destructor) costs one extra pointer per object (and per virtual inheritance). On a 64bit system, the overhead would of course be twice as much.

So, what do we learn from this? Virtual functions are evil, don't use them? No, surely not. Virtual functions are good and useful. But we should know that they are not free (especially not in combination with multiple inheritance, as shown).

killerbot:
what brings us to the topic, that way to many people overutilize multiple inheritance.
Try to avoid it as much as possible. You should only inherit from interfaces (abstract classes), occassionaly you need to inherit from more then 1 interface, but normally you shouldn't (rethink your design) .
Too many people use inheritance to reuse implementation, it should be used for behaviour (!! : IS A relation ship). Most implementation reuse can be done through aggregation.

Typical example :
Shape, Circle, Square, Rectangle :
Shape : base
Derived from shape : Circle, Square and Rectangle

Square is not dereived from rectangle !!!! Square can be implemented by having inside a Rectangle member.

Say you have the method : SetWidth()/SetHeight() and it's Get equivalents. Basic expectations is, they get/set what they say. For a rectangle you will not expect that SetWidth() would change the height !! But for a square setting one, also changes the other. So a square does not behave like a rectangle --> IS NOT A --> so no inheritance, but you can easlity implement a square on the inside by using a rectangle (eg : Square :SetHeight -> on the rectangle inside set height and width).

Note that many textbooks have been using this as an example, and have shown it WRONG !!!
Mathimatically a square is a rectangle ,but not in behaviour. And behaviour is interfaces, and interfaces are subject for inheritance.

Michael:
@Thomas

Your demostration is very interesting. Personally, I have always appreciated C++ multiple-inheritance (especially when programming with Java :D). Anyway, it has a cost as you correctly demonstrate. I just wonder if C++ Class Flattening could be used to reduce the overhead due to the virtual functions...

I am curious to know what all the books written by C++ Experts that I have bought, will say about it :D.

@Killerbot

As told above I like multiple-inheritance, but not wild inheritance. I just not use multiple-inheritance, because it exists. But I like that it is there in case of need. With Java it was different and I quite never felt comfortable with the interfaces and single inheritance.

Your examlple is also interesting and helpful.

The design of an application is a very important point and always underestimated. At the beginning, I just wanted to code and not waste my time with the design. Later, I had to change most of my code, because of errors and inefficiency. Now, I take more time to design my application in order to avoid problems later (but I still prefer to code :D).

Michael

killerbot:

--- Quote ---I am curious to know what all the books written by C++ Experts that I have bought, will say about it
--- End quote ---

Check out Scot Meyers and Herb Sutters their books ...

Navigation

[0] Message Index

[#] Next page

[*] Previous page

Go to full version