Google Groups no longer supports new Usenet posts or subscriptions. Historical content remains viewable.
Dismiss

Virtual function call from the constructor

3 views
Skip to first unread message

Yuriy Sorokin

unread,
Mar 20, 2003, 4:31:42 AM3/20/03
to
I have some base class with pure virtual function:

class TBase
{
protected:
vitrual void Execute() const=0;
public:
TBase(bool runExecute) {}
};

class TDerived:public TBse
{
private:
int somedata;
protected:
vitrual void Execute() const { /* using "somedata" */ }
public:
TDerived(bool runExecute):TBase(bool runExecute) { /* some specific
actions*/}
};

The main goal is to define BASE class such way that "Execute" member
function will be started just after the DERIVED constructor.
I do not want to explicitly add "Execute();" call to the end of the derived
constructor body. I want to add such code once into base class.

Unfortunately, we can not add "Execute();" call into the end of the base
constructor body, because Execute member function may use some data,
that is defined in derived class only and derived object will not have been
constructed since the moment of execution(Base class constructor is called
before Derived).

Is there some way to avoid this problem?

Thanks.

[ Send an empty e-mail to c++-...@netlab.cs.rpi.edu for info ]
[ about comp.lang.c++.moderated. First time posters: do this! ]

Francis Glassborow

unread,
Mar 21, 2003, 5:17:08 AM3/21/03
to
In message <b5a76r$1qv8$1...@igloo.uran.net.ua>, Yuriy Sorokin
<yu...@cad.ntu-kpi.kiev.ua> writes

>I have some base class with pure virtual function:
>
>class TBase
>{
> protected:
> vitrual void Execute() const=0;
> public:
> TBase(bool runExecute) {}
>};
>
>class TDerived:public TBse
>{
> private:
> int somedata;
> protected:
> vitrual void Execute() const { /* using "somedata" */ }
> public:
> TDerived(bool runExecute):TBase(bool runExecute)

At this point the type of the object being constructed is TBase and so
the compiler would attempt to run the pure virtual function. Obviously
this is an error.

> { /* some specific

This is the first place where the object under construction is both
accessible and has type TDerived. So it is here that you must run
runExecute.

>actions*/}
>};
>
>The main goal is to define BASE class such way that "Execute" member
>function will be started just after the DERIVED constructor.
>I do not want to explicitly add "Execute();" call to the end of the derived
>constructor body. I want to add such code once into base class.

You cannot. However you can call Execute() at the start of the derived
constructor body.

>


>Unfortunately, we can not add "Execute();" call into the end of the base
>constructor body, because Execute member function may use some data,
>that is defined in derived class only and derived object will not have been
>constructed since the moment of execution(Base class constructor is called
>before Derived).
>
>Is there some way to avoid this problem?

Well I do not know if I should show you this because it is pure hackery
and pointless hackery at that but just to show we can run Execute()
before entering the body of the derived ctor:

class TDerived {
// all your declarations
// and last, after all other data members
bool execute_called;
}

TDerived():execute_called(runExecute()){ // your code }

Note that runExecute must return a bool or something convertible to
bool.

Of course this does nothing useful:-)

--
ACCU Spring Conference 2003 April 2-5
The Conference you cannot afford to miss
Check the details: http://www.accuconference.co.uk/
Francis Glassborow ACCU

aiva...@hotmail.com

unread,
Mar 21, 2003, 11:35:03 AM3/21/03
to
If you implemented a factory method for constructing your objects to access
derived ones via pointer to base you can implement a call to Execute in the
factory method. To ensure user must use your factory you can make all
constructors private. Construct you objects first using factory, and then
make a call to Execute()

"Yuriy Sorokin" <yu...@cad.ntu-kpi.kiev.ua> schrieb im Newsbeitrag
news:b5a76r$1qv8$1...@igloo.uran.net.ua...

Christophe Brun

unread,
Mar 21, 2003, 11:45:53 AM3/21/03
to
Anyway, were your class absolutely free of any data members, you'll still
face a big problem with this scheme.
The point is that when an object gets constructed, constructors are called
in a canonical order, beginning with the constructor of the less derived
class and ending with the constructor of the most derived (which is your
actual) class. Now, what happens if you put the call to the virtual method
Execute() in the base class constructor ? Well... the only object
constructed at this time is the base object, isn't it ? Then, it should be
clear that the only version of Execute() that can be invoked is
Base::Execute()... In other words, virtuality (and polymorphism) is
irrelevant during construction.


On 20 Mar 2003 04:31:42 -0500, Yuriy Sorokin <yu...@cad.ntu-kpi.kiev.ua>
wrote:

--
Using M2, Opera's revolutionary e-mail client: http://www.opera.com/m2/

Rob

unread,
Mar 21, 2003, 11:46:44 AM3/21/03
to
"Yuriy Sorokin" <yu...@cad.ntu-kpi.kiev.ua> wrote in message
news:b5a76r$1qv8$1...@igloo.uran.net.ua...

Sure. There are plenty of ways. One simple one is to make the
constructors
of your classes protected, and have a friend function like

TBase *Create()
{
TBase *retval = NULL;
if (condition_1)
{
retval = new Derived_1;
}
else if (condition_2)
{
retval = new Derived_2;
}
// etc

if (retval != NULL) retval->Execute();

}


This approach (as written) gives the problem of a single function that
requires
knowledge of all classes derived from Base. But it illustrates the basic
idea.

However, there are various design patterns that can be used to avoid
dependency
chains like that.

Carl Daniel

unread,
Mar 21, 2003, 12:05:54 PM3/21/03
to
Yuriy Sorokin wrote:

> Is there some way to avoid this problem?

Yes. Use the Abstract Factory pattern and prohibit end-users from calling
the constructors in your class hierarchy. Unfortunately, that comes with a
cost of requiring that your objects be heap-based.

-cd

Makis Papapanagiotou

unread,
Mar 21, 2003, 12:08:51 PM3/21/03
to
Hello,

A usual way to solve the above, is to use a "Second level of initialization"
... as it is called
It is a standard way, just after the constructors, to call a "bool
initInstance()" function (second level of initialization). There, you can
call any aditional parts and perform some plausibility checks on your member
variables.
Only after that (of course, if the return result of initInstance() is true)
you can consider that the object creation is completed and ready to
function.


"Yuriy Sorokin" <yu...@cad.ntu-kpi.kiev.ua> wrote in message
news:b5a76r$1qv8$1...@igloo.uran.net.ua...

[ Send an empty e-mail to c++-...@netlab.cs.rpi.edu for info ]

Joshua Lehrer

unread,
Mar 21, 2003, 12:09:38 PM3/21/03
to
"Yuriy Sorokin" <yu...@cad.ntu-kpi.kiev.ua> wrote in message news:<b5a76r$1qv8$1...@igloo.uran.net.ua>...
> I have some base class with pure virtual function:
>
> class TBase
> {
> protected:
> vitrual void Execute() const=0;
> public:
> TBase(bool runExecute) {}
> };
>
> class TDerived:public TBse
> {
> private:
> int somedata;
> protected:
> vitrual void Execute() const { /* using "somedata" */ }
> public:
> TDerived(bool runExecute):TBase(bool runExecute) { /* some specific
> actions*/}
> };
>

Make TDerived un-instantiable by protecting it's constructors. Make a
subclass of TDerived (possibly generic) which instantiates TDerived
and thus TBase, and then calls Execute for you. This is the approach
that COM uses to call FinalConstruct:

template <typename T> struct Executioner : public T {
Executioner() : T() {
Execute();
}
template <typename P1> Executioner(const P1 &p1) : T(p1) {
Execute();
}
//etc... for more argument types
};

//you can obtain a pointer to dynamic memory:
TDerived * p1 = new Executioner<TDerived>;

//or a reference to a stack based object:
const TDerived & r1 = Executioner<TDerived>(true);

to make it even prettier, you can wrap this up in a creator function
to hide the template and do automatic template deduction.

joshua lehrer
factset research systems
NYSE:FDS

Alexander Terekhov

unread,
Mar 21, 2003, 6:04:04 PM3/21/03
to

Yuriy Sorokin wrote:
[...]

> Is there some way to avoid this problem?

There are many ways "to avoid this problem"... but nothing comes
close to a rather simple, straightforward, maintainable, etc.

<dreams on>

class T {
/* ... */
post T() { /* ... */ }; // post-constructor
pre ~T() { /* ... */ }; // pre-destructor
};

<dreams off>

http://google.com/groups?as_q=post%20pre&as_uauthors=tere...@web.de

regards,
alexander.

Michiel Salters

unread,
Mar 21, 2003, 6:48:45 PM3/21/03
to
"Yuriy Sorokin" <yu...@cad.ntu-kpi.kiev.ua> wrote in message news:<b5a76r$1qv8$1...@igloo.uran.net.ua>...
> I have some base class with pure virtual function:
>
> class TBase
> {
> protected:
> virtual void Execute() const=0;
> public:
> TBase(bool runExecute) {}
> };
>
> class TDerived:public TBase ...

> The main goal is to define BASE class such way that "Execute" member
> function will be started just after the DERIVED constructor.
> I do not want to explicitly add "Execute();" call to the end of the derived
> constructor body. I want to add such code once into base class.

This can't be done directly. As you noted, in Base::Base() you don't
have a derived class yet, and it is possible you won't have one, ever,
if the
derived class ctor decides to throw an exception.
You can of course define a class template Executor<T> : public T
whose ctor calls T::execute().

Regards,
Michiel Salters

Joachim Faulhaber

unread,
Mar 21, 2003, 6:53:18 PM3/21/03
to
"Yuriy Sorokin" <yu...@cad.ntu-kpi.kiev.ua> wrote in message news:<b5a76r$1qv8$1...@igloo.uran.net.ua>...

Dear Yuriy,

I have encounterd this kind of problem a couple of times. Your code
brings in a new flavor as it tries to call the constructor of an
abstract class in the initialisation list of a derived class.

> TDerived(bool runExecute):TBase(bool runExecute) { /* some specific
> actions*/}

This won't work because an abstract class (containing pure virtual
functions) can not be constructed.

Regards

Joachim

Francis Glassborow

unread,
Mar 22, 2003, 3:49:59 PM3/22/03
to
In message <6e725988.03032...@posting.google.com>, Joachim
Faulhaber <jo...@berlin.cortex-software.de> writes

>Dear Yuriy,
>
>I have encounterd this kind of problem a couple of times. Your code
>brings in a new flavor as it tries to call the constructor of an
>abstract class in the initialisation list of a derived class.
>
>> TDerived(bool runExecute):TBase(bool runExecute) { /* some specific
>> actions*/}
>
>This won't work because an abstract class (containing pure virtual
>functions) can not be constructed.

Of course it can, and is but only as a subobject of the derived class.
You can even call member functions of the base class but not pure
virtual ones, and virtual ones will have the static type of the base
class which is the type of the object under construction until that
phase has been completed.


--
ACCU Spring Conference 2003 April 2-5
The Conference you cannot afford to miss
Check the details: http://www.accuconference.co.uk/
Francis Glassborow ACCU

Joachim Faulhaber

unread,
Mar 24, 2003, 3:22:27 PM3/24/03
to
Francis Glassborow <francis.g...@ntlworld.com> wrote in message > Of course it can, and is but only as a subobject of the derived class.

> You can even call member functions of the base class but not pure
> virtual ones, and virtual ones will have the static type of the base
> class which is the type of the object under construction until that
> phase has been completed.
>

ok, I've got the lesson. The following code exemplifies
the hackery version of calling a 'base-pure' virtual function
in advance of the Derived::ctor's body.


class Base
{
public:
Base(int n): _n(n){}
virtual int prn()=0;
virtual int get(){return _n;};
private:
int _n;
};

class Derived : public Base
{
public:
Derived();
int prn();
int get() { return _i; }
private:
int _i;
};


int Derived::prn()
{
printf("answer %d\n", get());
return 42;
}

Derived::Derived():
Base(11),
_i(prn()) // able to call Derived::prn() although derived object
// is not completely constructed yet. prn calls get() of
// static type int Base::get()
{
prn();
}

void main()
{
Derived d;
}


On the first call of prn() in the Derived::ctor's initialisation
list the static typed version of Base::get() is called.

In the second call of prn in ctor's body the dynamically typed
Derived::get() is called. so the programm outputs

answer 11
answer 42

Now the benefits of pointless hackery finally shows up:

If I remove the implementation of get() in class::Base:

virtual int get()=0;

The programm still compiles and links with my ms visual c++ v.6
compiler. Then it crashes on the attempt to call get().

I don't really understand why the language (and compilers)
allows such windy constructions.

Francis Glassborow

unread,
Mar 25, 2003, 10:55:59 AM3/25/03
to
>On the first call of prn() in the Derived::ctor's initialisation
>list the static typed version of Base::get() is called.

I think that is wrong (though calling virtual functions in a constructor
is fraught with surprises) At this point the Base ctor has completed so
the type of the object is now Derived, albeit not yet fully initialised
and so it should be the Derived::get() called. My guess is that what you
got is a bug in the compiler.

>
>In the second call of prn in ctor's body the dynamically typed
>Derived::get() is called. so the programm outputs

No, it is still statically typed, but the static type is Derived (and I
believe that that is true from the moment that the Base ctor completes.

>answer 11
>answer 42
>
>Now the benefits of pointless hackery finally shows up:
>
>If I remove the implementation of get() in class::Base:
>
> virtual int get()=0;
>
>The programm still compiles and links with my ms visual c++ v.6
>compiler. Then it crashes on the attempt to call get().
>
>I don't really understand why the language (and compilers)
>allows such windy constructions.

I do not think it does.

--
ACCU Spring Conference 2003 April 2-5
The Conference you cannot afford to miss
Check the details: http://www.accuconference.co.uk/
Francis Glassborow ACCU

0 new messages