Virtual functions in constructors. Is it possible?

A

Alf P. Steinbach /Usenet

* Virchanza, on 05.07.2011 23:58:
I've been playing around with GCC, and it seems as though GCC changes
an object's V-Table pointer while the object is constructed from the
ground up (from Base class to furthermost Derived class).

Here's the code I tried:

#include<iostream>
using std::cout;

class Base {

private:

static void Call_Init(Base *const p)
{
p->Init();
}

public:

virtual void Init()
{
cout<< "This is Base::Init\n";
}

Base()
{
Call_Init(this);
}
};

class Derived : public Base {

public:

virtual void Init()
{
cout<< "This is Derived::Init\n";
}
};

int main()
{
Base a;
Derived b;
}

The output from this program is:

This is Base::Init
This is Base::Init

I think there's two possible explanations for this:

1) The "Call_Init" function is expanded inline and is not actually
consulting the object's V-Table pointer.

2) The "Call_Init" function does actually consult the object's V-Table
pointer, but when Call_Init is called, the object's V-Table pointer
points to the V-Table for the Base Class. Presumably then, the
object's V-Table pointer gets updated as each derived class undergoes
construction.

Is Number 2 the norm for all C++ compilers?

Yes.

See the FAQ, <url:
http://www.parashift.com/c++-faq-lite/strange-inheritance.html#faq-23.5>.

Or your favorite C++ textbook.


Cheers & hth.,

- Alf
 
W

Werner

I *did* try it.
And, as soon as I change it to reflect what I mean - this means removing the
FAIL_CONSTRUCTOR case and adding a InitFailed() -, everything works OK. BTW
the NO_INIT_CALL looks useless to me, so I removed it.

Unfortunately you cannot easily impose this requirement (that
their constructors may not throw) on derived classes (the
client). This makes this idiom very restrictive.

Furthermore, throwing from within init, even when calling InitFailed
still causes the leak (even when using an auto_ptr).

Output using your addition (courtesy of codepad, my
comments added):

//Options used...
//#define FAIL_CONSTRUCTOR
#define FAIL_INIT
//#define NO_INIT_CALL


1) Initializer //Parameter initialization from default
2) Allocation //new called.
3) VirtualBase //vbase constructor
4) Base //base constructor
5) ~Initializer //Parameter out of scope...
6) Base::Init() //Valid virtual call
7) Base::InitFailed() //ditto
8) !Oops, `Init` failed. //final catch, but
// where is Deallocation? This despite the
// fact that we used an autoptr (Oops, auto_ptr
// was never initialized, as new never completed...
9) !Memory leak. //... is still there, apart from the
//UB if we define FAIL_CONSTRUCTOR...

10) Finished.

Kind regards,

Werner
 

Ask a Question

Want to reply to this thread or ask your own question?

You'll need to choose a username for the site, which only take a couple of moments. After that, you can post your question and our members will help you out.

Ask a Question

Members online

No members online now.

Forum statistics

Threads
473,776
Messages
2,569,603
Members
45,189
Latest member
CryptoTaxSoftware

Latest Threads

Top