Sign in to follow this  
quaker

The Most Difficult Q in C++

Recommended Posts

Here is the most ever hardest issue in C++. How to make a virtual call inside a constructor, forcing the the correct virtual function to be called withing the constructor. I tried a solution but it did not work, to wrap the virtual function inside a local non-virtual function and call it instead. IT NOT WORK LIKE THAT! How?

Share this post


Link to post
Share on other sites
You don't. The language was designed to specifically prevent that kind of behavior.

Share this post


Link to post
Share on other sites
Variables in derived classes will not be initialised while the base constructor is running, so this would be dangerous to do.



class Base
{
int x;
public:
Base()
{
x = foo();
}

virtual int foo();
};


class Derived : public Base
{
int *somePointer;
Derived() : somePointer( new int(0) )
{
}

virtual int foo()
{
return *somePointer;
}
};






In this example, if Derived::foo() was called from the Base constructor, the most likely result would be a segfault at best, as somepointer would not be pointing anywhere in particulars.

Share this post


Link to post
Share on other sites
Anyone, please correct me if I'm wrong, but here goes;

Virtual functions are hidden pointers; you basically ask 'give me a pointer to...' when calling a virtual function and then that function gets excecuted.
In derived classes, the data member for such a refering pointer is overwritten with a pointer to the derived class' appropriate function. In the constructor of a base class, nothing is known of derived classes. Therefore, the pointers of the virtual members are not yet overwritten. You just get the base class' member.

It's actually quite handy and safe.

Share this post


Link to post
Share on other sites
Quote:
Original post by The Parrot
Anyone, please correct me if I'm wrong, but here goes;

Virtual functions are hidden pointers; you basically ask 'give me a pointer to...' when calling a virtual function and then that function gets excecuted.
In derived classes, the data member for such a refering pointer is overwritten with a pointer to the derived class' appropriate function. In the constructor of a base class, nothing is known of derived classes. Therefore, the pointers of the virtual members are not yet overwritten. You just get the base class' member.

It's actually quite handy and safe.


Yes, but that isnt what the OP desired. The OP wanted the derived classes function called from the base class ctor.

Share this post


Link to post
Share on other sites
Quote:

Anyone, please correct me if I'm wrong, but here goes;

Virtual functions are hidden pointers; you basically ask 'give me a pointer to...' when calling a virtual function and then that function gets excecuted.
In derived classes, the data member for such a refering pointer is overwritten with a pointer to the derived class' appropriate function. In the constructor of a base class, nothing is known of derived classes. Therefore, the pointers of the virtual members are not yet overwritten. You just get the base class' member.

It's actually quite handy and safe.


Almost.

Each instance of a class has only one pointer, to a VTable instance. The VTable instance holds the pointers to the virtual functions. IIRC, the VTable pointer isn't set until the end of construction. So when you call a virtual function you actually call obj.vtable->func_entry_N();

Share this post


Link to post
Share on other sites
Quote:
Original post by rip-off
Variables in derived classes will not be initialised while the base constructor is running, so this would be dangerous to do.

*** Source Snippet Removed ***

In this example, if Derived::foo() was called from the Base constructor, the most likely result would be a segfault at best, as somepointer would not be pointing anywhere in particulars.


Have you actually tried this? It doesn't work, and will call Base::foo() instead (and produce a link-time error since you haven't provided an implementation for it). The v-table pointer is setup in the construct of Derived, so when the constructor of Base is running the vtable still points to the functions in Base.

As SiCrane said, you don't. I believe it's actually impossible to do since you cannot take a pointer to the actual Derived::foo (this will return a pointer to a function that does the v-table lookup since foo() is a virtual rather than a pointer to the function itself), so even when trying to take a pointer to the function and reinterpret-casting this to Derived* it still calls Base::foo.

Quote:
Original post by Skarsha
IIRC, the VTable pointer isn't set until the end of construction.


It actually happens at the start of each constructor in the hierachy, so when the Base constructor is called this's vtable pointer is set to Base's vtable. Likewise when the Derived constructor is called. This ensures that if you call a virtual inside a constructor that the correct function is called up to that point in the construction.

Share this post


Link to post
Share on other sites
As has already been stated, you generally should not want such functionality. For ha-has, here is one way you could do it.


template< typename Type >
struct type_param
{
};

class base
{
public:
template< typename ChildType >
base( type_param< ChildType > )
{
ChildType& derived_this = static_cast< ChildType& >( *this );

derived_this.ChildType::some_virtual_function();
}

virtual void some_virtual_function() const = 0;
};

class derived
: public base
{
public:
derived()
: base( type_param< derived >() )
{
}
protected:
// Call this constructor from children of derived
template< typename ChildType >
derived( type_param< ChildType > type_arg )
: base( type_arg )
{
}
public:
void some_virtual_function() const
{
// Do Stuff here
}
};


Share this post


Link to post
Share on other sites
Quote:
Original post by joanusdmentia
Quote:
Original post by rip-off
Variables in derived classes will not be initialised while the base constructor is running, so this would be dangerous to do.

*** Source Snippet Removed ***

In this example, if Derived::foo() was called from the Base constructor, the most likely result would be a segfault at best, as somepointer would not be pointing anywhere in particulars.


Have you actually tried this? It doesn't work, and will call Base::foo() instead [snip...]


Yeah, I know. Hence the "if" in my sentence. [smile]

Share this post


Link to post
Share on other sites
Quote:
Original post by Polymorphic OOP
As has already been stated, you generally should not want such functionality. For ha-has, here is one way you could do it.

*** Source Snippet Removed ***


Of course, that code relies on undefined behavior, so it may not actually call the derived class' version of the virtual function.

Share this post


Link to post
Share on other sites

Create an account or sign in to comment

You need to be a member in order to leave a comment

Create an account

Sign up for a new account in our community. It's easy!

Register a new account

Sign in

Already have an account? Sign in here.

Sign In Now

Sign in to follow this