Avoid virtual function when calling common code in destructor

  • Permalink
  • submit to reddit
  • Email
  • Follow


Hello,

I have a class with a logical disconnect() function. This disconnect
function may be called manually and will be called in the destructor.
However, I'm not quite sure how to build this function.  I want the
disconnect() function to be virtual, but calling a virtual function
from a destructor is faux pas, correct?  Is it okay in this situation,
or otherwise, how can I do this?

Thank you,
Kevin


      [ See http://www.gotw.ca/resources/clcm.htm for info about ]
      [ comp.lang.c++.moderated.    First time posters: Do this! ]
0
Reply kevin.grigorenko (2) 1/12/2005 8:55:32 PM

See related articles to this posting

Kevin Grigorenko wrote:
> Hello,
>
> I have a class with a logical disconnect() function. This disconnect
> function may be called manually and will be called in the destructor.
> However, I'm not quite sure how to build this function.  I want the
> disconnect() function to be virtual, but calling a virtual function
> from a destructor is faux pas, correct?  Is it okay in this situation,
> or otherwise, how can I do this?

There's nothing wrong with calling a virtual function in a destructor,
however, the function will resolve as if the type of the object is
of the type of the destructor.

The thing you can't do is make a virtual call to a PURE VIRTUAL
function in a destructor.

      [ See http://www.gotw.ca/resources/clcm.htm for info about ]
      [ comp.lang.c++.moderated.    First time posters: Do this! ]
0
Reply Ron 1/13/2005 12:05:57 PM

Calling a virtual function from a destructor calls the function in the
current object. You have to write your disconnect() so that it behaves
well when it is called during destruction.

struct A {
virtual void disconnect() {} //#1
virtual ~A() { disconnect(); } //Calls #1 while destruction
};

struct B : public A {
virtual void disconnect() {} //#2
virtual ~B() { disconnect(); } //Calls #2 while destruction
};


--lsu


      [ See http://www.gotw.ca/resources/clcm.htm for info about ]
      [ comp.lang.c++.moderated.    First time posters: Do this! ]
0
Reply L 1/13/2005 4:38:19 PM

On 12 Jan 2005 15:55:32 -0500, Kevin Grigorenko  
<kevin.grigorenko@gmail.com> wrote:

> I have a class with a logical disconnect() function. This disconnect
> function may be called manually and will be called in the destructor.
> However, I'm not quite sure how to build this function.  I want the
> disconnect() function to be virtual, but calling a virtual function
> from a destructor is faux pas, correct?  Is it okay in this situation,
> or otherwise, how can I do this?

First, you might consider to get rid of disconnect function, placing all  
cleanup in destructors. This could be the best solution with regards to  
implementation effort.

Second, the context implies that you use interface based design. If this  
is so, you may want to employ proxy design pattern or handle-envelope (aka  
pimpl) idiom, that is, you wrap all your objects with a proxy object that  
calls disconnect function from its destructor.

Example:

     struct resource
     {
         virtual void do_some() = 0;
         virtual void disconnect() = 0;
         virtual ~resource() {}
     };

     struct resource_proxy
     {
         typedef std::auto_ptr<resource> wrapped_ptr;
         wrapped_ptr const w_; // const here makes resource_decorator  
noncopyable

         // forwarding functions
         void do_some() { w_->do_some(); }
         void disconnect() { w_->disconnect(); }

         resource_proxy(wrapped_ptr w) : w_(w) {}
         ~resource_proxy() { this->disconnect(); }
     };

Client functions only deal with resource_proxy, which is initialized with  
some concrete resource object from your resource hierarchy.

-- 
Maxim Yegorushkin

      [ See http://www.gotw.ca/resources/clcm.htm for info about ]
      [ comp.lang.c++.moderated.    First time posters: Do this! ]

0
Reply Maxim 1/13/2005 8:03:03 PM

Ron Natalie wrote:
> Kevin Grigorenko wrote:
>>I have a class with a logical disconnect() function. This disconnect
>>function may be called manually and will be called in the destructor.
>>However, I'm not quite sure how to build this function.  I want the
>>disconnect() function to be virtual, but calling a virtual function
>>from a destructor is faux pas, correct?  Is it okay in this situation,
>>or otherwise, how can I do this?
> 
> There's nothing wrong with calling a virtual function in a destructor,
> however, the function will resolve as if the type of the object is
> of the type of the destructor.

It's debatable whether calling a virtual function is 'correct' in
a destructor; for example, when you consider the OP's problem.

> The thing you can't do is make a virtual call to a PURE VIRTUAL
> function in a destructor.

You shouldn't call a pure virtual anywhere :)

Back to the OP's problem: when cleanup activity is defined/refined
in subclasses, you cannot depend on it happening through the parent
destructor, since the destructor's type context never reaches into
the subtypes.

The behavior you want requires that certain points of behavior retain
their dyanmism beyond the start of the destruction phase, or that their
final specialization happens in the same class where you call them
in the destructor.

You can do that by messing around with the type system, and placing
instantiation barriers at various places, so that a destructor call
to disconnect() always hits the right place.  This is not simple,
nor good looking; you would have to make sure that disconnect()
[and similar points of specialization] do not get refined/redefined
in the subclasses (otherwise, we're back where we started).

Or, you can partition your classes, so that the connection object
is not embedded in the class under focus, and you can disconnect()
it through the appropriate mechanism before you destroy it; e.g.:
something like this:

     class MyClass {
        connection_type *cnxn;
     public:
        virtual ~MyClass() {
            cnxn->disconnect();
            delete cnxn;
            /// more destruction ...
        }
        /// etc ....
     };

-- 
A. Kanawati
NO.antounk.SPAM@comcast.net

      [ See http://www.gotw.ca/resources/clcm.htm for info about ]
      [ comp.lang.c++.moderated.    First time posters: Do this! ]
0
Reply Antoun 1/13/2005 9:50:06 PM
comp.lang.c++.moderated 10585 articles. 6 followers. Post

4 Replies
205 Views

Similar Articles

[PageSpeed] 59

  • Permalink
  • submit to reddit
  • Email
  • Follow


Reply:

Similar Artilces:

calling virtual destructors and virtual functions
Say I have a class A, and a class B that inherits from A. Now A (and B) has a virtual destructor and a virtual function F(); If I now make these statements A* ptrA = new B; ptrA->F(); delete ptrA then in the statement ptrA->F(), by means of the polymorph behavior, the F() of class B is called. But the F() of class B only. And in delete ptrA, both destructors of class A and B are called. Is this right? Because then the two statements behave differently. Somehow, for a moment, I was thinking that in the call ptrA->F(), both virtual functions of class A and B should be processed. *...

Calling virtual functions from destructors?
Hi I've had a problem with gcc mac osx which I think I figured out. I would like to double check with people here to see if my understanding is correct: I have a class A which class B inherit from. A has a pure virtual function virtual in f1() = 0. In B I implement this function and the compiler works out the code. However from A's destructor B can be compiled and then the runtime aborts with saying that a call to a pure virtual function is not allowed. I'm assuming that B's destructor has been called before A's destructor and thus it won't allow me to call the...

clarification
Hello class A { public: virtual void Func1() = 0; void Func1Caller() { Func1(); } ~A() { Func1Caller(); } }; class B : public A { public: virtual void Func1() { printf("this is func1\n"); } }; int main() { B t; return 0; } It seems that VC is not allowing Func1Caller() to call Func1() from the destructor. Don't know if this a C++ issue or a compiler issue. Can someone clarify and provide a workaround? -- Elias Every class is better has own constructor and deconstructor itself, even if compiler allow you do that. Class A func1 alway be called In ...

Problem with virtual functions called from a destructor
This is a simplified version of the situation (the actual situation is quite more complex, but when stripped to the bare minimum, it's like this): class BaseClass { public: virtual void cleanup(); virtual ~BaseClass() { cleanup(); } }; The cleanup() function is not only called when destroying the object but also at other times during the lifetime of the object, and it's usually called through a BaseClass pointer and sometimes implemented in a derived class. Naturally the problem is that the BaseClass destructor will not call the implementation of cleanup() in the deri...

avoiding virtual call with pointer to member function
Hi to all, a newbie question. Is it possible to avoid the virtual mechanism with pointers to members syntax the same way it's done with an explicit call ( obj.Base::Func() )? It would be useful for something I'm doing... check out the trivial program down here... Thanks in advance, Francesco #include <iostream> struct Base { virtual ~Base() {} virtual void Do() const { std::cout << "Base\n"; } }; struct Der : public Base { virtual void Do() const { std::cout << "Der\n"; } }; int main() { Der obj; obj.Base::Do(); // avoid virtual call...

Calling pure virtual functions from an abstract class constructor or destructor.
I'm trying to understand the scope of 10.4/6: struct C1 { void void bar () = 0; }; struct C2 : public C1 { C2 () : C1() {} void void bar () { } }; struct B : public C2 { B (); virtual void foo () = 0; }; B::B () : C2() { foo (); // (1) undefined from 10.4/6 bar (); // (2) undefined? } My interpretation of 10.4/6 makes both of these undefined behaviour. However, I do not see a justification for disallowing (2). Am I understanding something in the paragraph? Regards, Richard -- Richard Corden ---...

calling virtual function from within another virtual function
Hi Guys, Is Ok to invoke a virutal function from within virtual function. Specifically here is the example I tried and it seems to have worked: (what I am doing is derived class::foo() (foo is virtual)invokes base case implementation of foo(), which in turn calls bar() thats virutal too . So I am reusing some part of logic which is common to both base and derived and overriding other part which is different by using 2 virtual functions like this) #include <iostream.h> using namespace std; class C { public: virtual void foo(int foo) { cout << "in C::foo() foo="...

calling virtual function results in calling function of base class ...
Hi, after browsing FAQ and archive for a while I decided that the following is a legal question. Consider this: Class Base { public: Base() {} Base(A* a, B* b); virtual A* foo(P* p, S& s); // using myA and myB protected: A* myA; B* myB; }; class Der : public Base { public: Der(O* o) : Base(), myO(o) {} A* foo(P* p; S& s); // not using myA and myB private: O* myO; }; class Bogus { public: Bogus(Base* b) : myBase(b) {} void bar() { ... myBase->foo(p,s); ... } private: Base* myBase; }; int main(/*args*/) { ... Der der(someO); Bogus* bogus = new Bogus(d...

calling virtual function results in calling function of base class ... #2
On Andreas Lagemann <andreas.lagemann@freenet.de> wrote: > > Class Base > { > public: > Base() {} > > Base(A* a, B* b); > > virtual A* foo(P* p, S& s); // using myA and myB Make sure you have a virtual destructor, private copy constructor and private assignment operator. > Executing this results in Base::foo being called instead of Der::foo Did you make a typo or something. It will call Der::foo if your foo signature is exact the same in Der. Are you sure you use pointers when you are passing the Der object as a Base object? To make sure use pri...