Re: Virtual functions in constructors. Is it possible?
 
* Anonymous, on 04.07.2011 20:41:
class VirtualBase {
protected:
     class Initializer;
     friend class Initializer;
     class Initializer {
     public:
         Initializer() {
             std::cout << "Initializer" << std::endl;
             p = 0;
         }
         ~Initializer() {
             std::cout << "~Initializer" << std::endl;
             if (p)
                 p->Init(); // call the virtual function
         }
         // might be private if VirtualBase is declared as friend...
         void Register(VirtualBase* b) const {
             p = b;
         }
     private:
         mutable VirtualBase* p;
         // private and not implemented
         Initializer(const Initializer&);
         void operator =(const Initializer&);
     };
public:
     VirtualBase(const Initializer& i) {
         std::cout << "VirtualBase" << std::endl;
         i.Register(this);
     }
private:
     virtual void Init() = 0;
     // will be called immediately after the constructor
     // of the most derived class
};
// This is the actual hierarchy
class Base : public virtual VirtualBase {
public:
     Base(const VirtualBase::Initializer& i = Initializer()) : VirtualBase(i) {
         std::cout << "Base" << std::endl;
     }
     ~Base() {
         std::cout << "~Base" << std::endl;
     }
     void Init() {
         std::cout << "Base::Init()" << std::endl;
     }
};
class Derived : public Base {
public:
     //  Derived() : Base() {} // compile-time error as wanted
     Derived(const VirtualBase::Initializer& i = Initializer()) :
     Base(i), /* Base(i) is optional...*/
     VirtualBase(i)
     {
         std::cout << "Derived" << std::endl;
     }
     ~Derived() {
         std::cout << "~Derived" << std::endl;
     }
     void Init() {
         std::cout << "Derived::Init()" << std::endl;
     }
};
int main()  {
   Base x;  // calls Base::Init
   Derived y ; // calls Derived::Init
   return( 0 ) ;
}
I reworked your example to show off the memory leak problem that I mentioned.
In addition this led me to realize one problem that I didn't think of earlier, 
namely that in the event of a failing constructor, the Initializer destructor 
will be calling a virtual method on a non-existent object, invoking UB.
Here's the reworked code, just play with the macro symbols NO_INIT_CALL, 
FAIL_CONSTRUCTOR and FAIL_INIT:
<code>
#include <iostream>
#include <stdexcept>
#include <stdlib.h>
using namespace std;
namespace g {
     int nObjectsAllocated  = 0;
}    // namespace g
class VirtualBase {
protected:
     class Initializer;
     friend class Initializer;
     class Initializer {
     public:
         Initializer() {
             cout << "Initializer" << endl;
             p = 0;
         }
         ~Initializer() {
             cout << "~Initializer" << endl;
             #ifndef NO_INIT_CALL
                 if (p)
                     p->Init(); // call the virtual function
             #endif
         }
         // might be private if VirtualBase is declared as friend...
         void Register(VirtualBase* b) const {
             p = b;
         }
     private:
         mutable VirtualBase* p;
         // private and not implemented
         Initializer(const Initializer&);
         void operator =(const Initializer&);
     };
public:
     VirtualBase(const Initializer& i) {
         cout << "VirtualBase" << endl;
         i.Register(this);
     }
private:
     virtual void Init() = 0;
     // will be called immediately after the constructor
     // of the most derived class
};
// This is the actual hierarchy
class Base : public virtual VirtualBase {
public:
     static void* operator new( size_t size )
     {
         cout << "Allocation" << endl;
         ++g::nObjectsAllocated;
         return ::operator new( size );
     }
     static void operator delete( void* p )
     {
         cout << "Deallocation" << endl;
         --g::nObjectsAllocated;
         return ::operator delete( p );
     }
     Base(const VirtualBase::Initializer& i = Initializer()) : VirtualBase(i) {
         cout << "Base" << endl;
         #ifdef FAIL_CONSTRUCTOR
             throw runtime_error( "Oops, `Base::Base` failed." );
         #endif
     }
     ~Base() {
         cout << "~Base" << endl;
     }
     void Init() {
         cout << "Base::Init()" << endl;
         #ifdef FAIL_INIT
             throw runtime_error( "Oops, `Init` failed." );
         #endif
     }
};
int main()
{
     int result = EXIT_FAILURE;
     try
     {
         Base* p = new Base;  // calls Base::Init
         cout << endl;
         delete p;
         result = EXIT_SUCCESS;
     }
     catch( exception const& x )
     {
         cerr << "!" << x.what() << endl;
     }
     if( g::nObjectsAllocated > 0 )
     {
         cerr << "!Memory leak." << endl;
     }
     cout << "Finished." << endl;
     return result;
}
</code>
As you can see the scheme, at least in its current incarnation, is not very 
exception-friendly: invoking UB, and leaking memory.
Can it be made exception safe?
Cheers & hth.,
- Alf
-- 
blog at <url: http://alfps.wordpress.com>