473,387 Members | 1,904 Online
Bytes | Software Development & Data Engineering Community
Post Job

Home Posts Topics Members FAQ

Join Bytes to post your question to a community of 473,387 software developers and data experts.

When to define a virtual destructor

Hello people,
I know that in a base class you should define the destructor as virtual but is there any cases that you define a destructor as virtual. In the case when you implement assignment operator and copy constructor you need to implement the destructor as well but does it need to be virtual too or not?

many thanks
Sep 13 '07 #1
16 3056
Savage
1,764 Expert 1GB
Hello people,
I know that in a base class you should define the destructor as virtual but is there any cases that you define a destructor as virtual. In the case when you implement assignment operator and copy constructor you need to implement the destructor as well but does it need to be virtual too or not?

many thanks

I really don't understand what are you trying to say.

Could you please rephrase somehow?

Savage
Sep 13 '07 #2
I really don't understand what are you trying to say.

Could you please rephrase somehow?

Savage
well what I'm saying basically is when do you define a destructor as virtual besides in inheritance and for the base class.
Sep 13 '07 #3
RRick
463 Expert 256MB
Whew! Destructors and copy methods! While this is an innocent question, you have really opened up a big C++ can of worms.

First of all, the destructor, copy constructor and operator= are known as the "Big 3" methods and many times are grouped together. Some sources say that if you implement one of them, you should implement all of them. In this case, disabling a method by making it private counts as an implementation.

Notice that the above discussion makes no mention of the destructor being virtual. You must make the destructor virtual, if you have any plans to derive from this class. If you don't, you can introduce a bug due to "splicing". Does this mean the base class also has to define the copy methods, too? Only if the desctructor is releasing resources. I believe this is one of the few exceptions to the Big 3 rule.

The operator= can be made virtual (I think) but I haven't seen an example for doing this. Most cases for using operator= is between the same class. I believe operator= can be used to copy between base and derived classes (but I wouldn't bet the house on it). To me, this sounds like a diaster.

One last point on copying. There is a real need to make copies of derived objects from base class pointers. In this case, a technique called cloning is used where a virtual clone method is created.
Sep 13 '07 #4
Savage
1,764 Expert 1GB
well what I'm saying basically is when do you define a destructor as virtual besides in inheritance and for the base class.
It's good to have always a virtual destructor,you might need to derive from that class in a future to avoid reinventing the wheel,so whenever you can make it virtual unless your primary goal is speed.

Savage
Sep 13 '07 #5
weaknessforcats
9,208 Expert Mod 8TB
All of the above answers are incorrect.

A virtual destructor has nothing to do with the "Big 3" or the assignment operator.

You have to understand that only the compiler can create and destroy objects. As a courtesy, on creation the compiler will call a constructor so you can intialize any class members that haven't alreay been initialized. On destruction, a courtesy call to your destructor allows you to release any resources you may have allocated or to do any last minute work as the result of the object being destroyed.

Where a hierarchy is involved with a base class having virtual functions, the intent is to use base class pointers and references with derived objects. So, when you delete a base class pointer or reference, the base class destructor is called. And that's all.

If you you want your derived class destrutctor called, then the base class destructor must be virtual. In this case, the derived class destructor is called followed by a call to the base class destrcutor.

The rule is: If your base class has virtual functions, then it must have a virtual destrcutor. Otherwise, it's a design error.

A base class with no virtual functions and a virtual destrcutor is likewise a design error.
Sep 24 '07 #6
RRick
463 Expert 256MB
Actually, all of the above answers are correct; at least within their posts.

Savage took a safe path and suggested that all objects should have virtual destructors. This would stop the base class design flaw W4cats mentioned.

I personally don't care for this approach, but then I usually have access to the base class code, and can fix the above mentioned design flaw by modifying the destructor directly. If I can't access the original code, then I can wrap my own class around the offending object and hide its bad design with protected inheritence.

It might be my old C style coding habits, but I don't like making a class virtual ( and creating a virtual lookup table) unless it is really needed.
Sep 25 '07 #7
weaknessforcats
9,208 Expert Mod 8TB
It might be my old C style coding habits, but I don't like making a class virtual ( and creating a virtual lookup table) unless it is really needed.
Actually, this is exactly what you want. The base class object is really part of the derived object. When you call a base class private virtual method using a base class pointer, you want the call to be to the derived class override.

That means in object-oriented programming you base class will always need a vtbl.

Check out separating the interface from the implementation by reading up on the desing pattern Template Method.

I say again, a class with virtual functions and no virtual destructor is a design error.
Sep 25 '07 #8
Savage
1,764 Expert 1GB
Actually, this is exactly what you want. The base class object is really part of the derived object. When you call a base class private virtual method using a base class pointer, you want the call to be to the derived class override.

That means in object-oriented programming you base class will always need a vtbl.

Check out separating the interface from the implementation by reading up on the desing pattern Template Method.

I say again, a class with virtual functions and no virtual destructor is a design error.
Then why you said that my statement is incorrect?

I did said that it's good to always have a vdestructor,except when your goal is speed.

Savage
Sep 25 '07 #9
weaknessforcats
9,208 Expert Mod 8TB
Then why you said that my statement is incorrect?

I did said that it's good to always have a vdestructor,except when your goal is speed.
Sorry. I was referring to RRick's post #7.

Your statement of having virtual destructors for no reason on the off chance you will derive from the class in the future does not hold water. The reason is that this is a concrete class. That is, a class from which objects can be created.

When you derive from a concrete class, you cannot override base class methods since they aren't virtual. Your derived methods will just hide the base methods and remove that functionality from your derived class. That forces code like:
Expand|Select|Wrap|Line Numbers
  1. void Derived::AMethod(int arg)
  2. {
  3.        //Derived code goes here???
  4.        Base::AMethod();    //recover base class functionality
  5.        //Or does it go here???
  6. }
  7.  
Unfortuntately, now you can't tell whether the Base method call is a pre-condtion or a post-condition in the derived class and therefore have introduced ambiguity.

So the rule is: Never derive from a concrete class.

When you do derive, the base class will have virtual methods and that requires the virtual destructor.
Sep 26 '07 #10
RRick
463 Expert 256MB
Your derived methods will just hide the base methods and remove that functionality from your derived class.
......
Unfortuntately, now you can't tell whether the Base method call is a pre-condtion or a post-condition in the derived class and therefore have introduced ambiguity.
I don't see how derived classes get around the pre/post-condition problem you describe. The base class method is hidden to the derived class whether it is virtual or not.

Are you saying that overwriting a method somehow stops this from being a necessity? I don't see how. If you want the derived class to use the base class virtual method (which is not an unreasonable request), you run into the same condition issues. In this case, you have to work out the pre/post issues.
Sep 26 '07 #11
weaknessforcats
9,208 Expert Mod 8TB
I don't see how derived classes get around the pre/post-condition problem you describe. The base class method is hidden to the derived class whether it is virtual or not.

Are you saying that overwriting a method somehow stops this from being a necessity? I don't see how. If you want the derived class to use the base class virtual method (which is not an unreasonable request), you run into the same condition issues. In this case, you have to work out the pre/post issues.
First, I assume the derived class is overriding a base class private virtual method. Most likely, the method is also private in the derived class. That is the base class public methods (the hierarchy interface) are not virtual.


If this is not so, then the derived class really can't be called IS-A with respect to the base class. The relationship would be more like KIND-A or SORT-OF.

Second, the private base class methods being overriden would be a) pure virtual methods to force the override or b) hooks. Hooks have no code.

On the other hand, if this is a case of base class public virtual methods being overriden by public derived class virtual methods, then the object-oriented design is not correctly implemented since the interface methods (in the base class) have not been separated from the implementation (the derived class methods. Thay haven been replaced.

Failing to separate the interface from the implementation is the equivalent of having public data members. Except here you call the function to get the result. The net effect is that the implementation is scattered throughout user land and when a redesign is required, all that user code breaks.

Encapsulation is measured by how much code breaks when you change the class implementation. By that mesaure public virtual methods break encapsulation.

This gets us back to overriding base class private methods which are either pure or have no code (hooks). And this situation requires a virtual destructor in the base class.

I realize the textbooks use public virtual functions but I am persuaded this is bad design.

Check out Design Patterns by Erich Gamma, et al and read up on the Template Method.

There are also writing by Scott Meyers on this exact issue.
Sep 27 '07 #12
RRick
463 Expert 256MB
What I'm hearing here is a conservative approach to class creation. Great emphasize is placed on creating objects that are rock solid and robust. Great emphasize is placed on removing/hiding the implementation from the client (and future developers), through the use of pure interfaces and private class protections.

While this is admirable there is a down side: limited code reuse and limited inheritence (which also affects code reuse). The general pattern here is to create a base class that is rock solid (a good idea), but usually can only support a limited and specific purpose. Private protections on all non-public methods restricts the code reuse of the base class. The derived class is in a similar situation. It can be used to create a single special case for the base class, but deriving again from the derived class is restricted due to private permissions.

Don't get me wrong, I agree that separating interface from implementaion is important (and Scott Meyers does a good job of describing this). There are times objects need to protect themselves from any modification and there are times they don't. Designing objects is a balance of time, requirements, and expected clients.

Public virtual methods might have some issues, but to ignore them in general, ignores their greatest asset: code reuse. For example, the Java toString virtual method is a major concept that works well beyond any of these limitations.
Sep 28 '07 #13
weaknessforcats
9,208 Expert Mod 8TB
Reuse is fine. But the fact is that most modifcations are done by ditch-and-recode. Encapsulation trumps reuse every time. By keeping the ripple of change to a minimum means you ditch the smallest amount of code.

That means you do not expose your implementation.

And that means private virtual functions in the base class.

Also, keep in mind:
1) the derived class does not need to support only base class methods. It can have addtional methods not in the base class at all and you can call these methods using a base class pointer and a Visitor object.

That is, only part of the derived class need be object-oriented. The rest of it can be object-based.

2) You can add methods to a derived class without changing the either the base or the derived class by using a Visitor. And you can call these methods by using a base class pointer and a Visitor object.

This will give you 100% reuse and still retain the private virtual functions.

But, what the hey, code is being written that still uses global variables, public data members, typecasts, macros, passing pointers all over, etc. With that in mind, these private virtual functions are in another universe.
Sep 28 '07 #14
RRick
463 Expert 256MB
I've found that object design is a push and pull situation based on different requirements. If you push encapsulation to the limit, then you get rock hard objects for specific tasks, but further derivation is difficult or complex. This will lead to ditching the code, but then crappy code is another good reason.

On the other hand, loose public access to an object is generally a catastrophe and further derivation is just plain dangerous. I look for a middle ground that will maximize what is needed for the situation.

As for the visitor, it is useful for specific situations, but is way too complex to to be used to implement simple code reuse. You just don't get enough utility from the effort.

BTW: I have never heard you mention "protected" class access. It seems to be the forgotten step child in the C++ world. I'm not trying to turn this into a 50 post message, but from what have you heard?
Sep 29 '07 #15
weaknessforcats
9,208 Expert Mod 8TB
BTW: I have never heard you mention "protected" class access. It seems to be the forgotten step child in the C++ world. I'm not trying to turn this into a 50 post message, but from what have you heard?
Starting with:
1) public inheritance is type inheritance
2) private inheritance is implementation inheritance
3) protected is design inheritance

You can use protected derivation for mix-in classes. The idea is that that base class is not completely implemented and the derived class completes the implementation. Correctly used, it is the derived class that is used to create objects and execute methods. The base class(es) just provide common processsing and not not intended to stand on their own. Kinda like Lego parts.

As a result, you should almost never see this. However, I see it a lot from developers that are too lazy to write code in the base class for data access and therefore expose the members to the derived class because it's handy. This does weaken encapsulation but is less a problem than a public data member.

Please keep your comments coming. You appear well-informed and there is a great chance I can learn from you.
Sep 29 '07 #16
RRick
463 Expert 256MB
Please keep your comments coming. You appear well-informed and there is a great chance I can learn from you.
Thanks. The feeling is mutual.

I joined theScripts with the intention of honing my C++ skills. This discourse has been gotten me to reconsider some of the basic assumptions I use for my design process.
Oct 1 '07 #17

Sign in to post your reply or Sign up for a free account.

Similar topics

11
by: Stub | last post by:
Please answer my questions below - thanks! 1. Why "Derived constructor" is called but "Derived destructor" not in Case 1 since object B is new'ed from Derived class? 2. Why "Derived destructor"...
37
by: WittyGuy | last post by:
Hi, I wonder the necessity of constructor and destructor in a Abstract Class? Is it really needed? ? Wg http://www.gotw.ca/resources/clcm.htm for info about ]
26
by: pmizzi | last post by:
When i compile my program with the -ansi -Wall -pedantic flags, i get this warning: `class vechile' has virtual functions but non-virtual destructor, and the same with my sub-classes. But when i...
8
by: Pete C | last post by:
In this section of the FAQ: http://www.parashift.com/c++-faq-lite/pointers-to-members.html#faq-33.10 an abstract destructor is given a definition with the cryptic comment "It's faster this...
22
by: ypjofficial | last post by:
Hello All, I have following doubt.. class abstractclass { public: abstractclass(){} virtual void method()=0; };
5
by: druberego | last post by:
I read google and tried to find the solution myself. YES I do know that you can get undefined references if you: a) forget to implement the code for a prototype/header file item, or b) you forget...
7
by: eric | last post by:
hello i'm confused by an example in the book "Effective C++ Third Edition" and would be grateful for some help. here's the code: class Person { public: Person(); virtual ~Person(); // see...
8
by: Shraddha | last post by:
What is the use of "PURE vitual distructors"? And why we can not have vitual constructors?
8
by: lmfmaw | last post by:
Hi all, I've hit the wall with this "fairly" simple problem. As you can see in the code below, my destructors don't do their job as they are supposed to (I left them empty for this example). I'm...
0
by: taylorcarr | last post by:
A Canon printer is a smart device known for being advanced, efficient, and reliable. It is designed for home, office, and hybrid workspace use and can also be used for a variety of purposes. However,...
0
by: ryjfgjl | last post by:
If we have dozens or hundreds of excel to import into the database, if we use the excel import function provided by database editors such as navicat, it will be extremely tedious and time-consuming...
0
BarryA
by: BarryA | last post by:
What are the essential steps and strategies outlined in the Data Structures and Algorithms (DSA) roadmap for aspiring data scientists? How can individuals effectively utilize this roadmap to progress...
1
by: nemocccc | last post by:
hello, everyone, I want to develop a software for my android phone for daily needs, any suggestions?
1
by: Sonnysonu | last post by:
This is the data of csv file 1 2 3 1 2 3 1 2 3 1 2 3 2 3 2 3 3 the lengths should be different i have to store the data by column-wise with in the specific length. suppose the i have to...
0
by: Hystou | last post by:
There are some requirements for setting up RAID: 1. The motherboard and BIOS support RAID configuration. 2. The motherboard has 2 or more available SATA protocol SSD/HDD slots (including MSATA, M.2...
0
marktang
by: marktang | last post by:
ONU (Optical Network Unit) is one of the key components for providing high-speed Internet services. Its primary function is to act as an endpoint device located at the user's premises. However,...
0
by: Hystou | last post by:
Most computers default to English, but sometimes we require a different language, especially when relocating. Forgot to request a specific language before your computer shipped? No problem! You can...
0
jinu1996
by: jinu1996 | last post by:
In today's digital age, having a compelling online presence is paramount for businesses aiming to thrive in a competitive landscape. At the heart of this digital strategy lies an intricately woven...

By using Bytes.com and it's services, you agree to our Privacy Policy and Terms of Use.

To disable or enable advertisements and analytics tracking please visit the manage ads & tracking page.