Can pure virtual function be called in base class constructor?

P

PengYu.UT

Hi,

A pure function is called in the base function constructor. It generate
a run time error: "pure virtual method called".

My problem is that class A have some derived classes. I want A's
constructor change its behaviour accounting to the derived class.

I tried to make A::fun() not pure virtual but virtual. It doesn't
generate any error. But A::fun() is called in A's construction, while I
want B::fun() be called. I just don't want to define a default virtual
function.

I'm wondering if there is any work around to solve this problem.

Best wishes,
Peng


#include <iostream>

class A{
public:
A(){ fun();}
virtual void fun() = 0;
};

class B : public A{
public:
virtual void fun(){
std::cout << __PRETTY_FUNCTION__ << std::endl;
}
};

int main(int argc, char *argv[])
{
B b;
}
 
V

Victor Bazarov

A pure function is called in the base function constructor. It
generate a run time error: "pure virtual method called".

My problem is that class A have some derived classes. I want A's
constructor change its behaviour accounting to the derived class.

I tried to make A::fun() not pure virtual but virtual. It doesn't
generate any error. But A::fun() is called in A's construction, while
I want B::fun() be called. I just don't want to define a default
virtual function.

What you're trying to accomplish goes against a very basic principle:
member functions shall not be called for an object whose construction
hasn't completed. If you're trying to call B::fun from A::A, the B
object hasn't finished constructing. Java is notoriously bad about
this particular behaviour and it is a constant cause of trouble.
I'm wondering if there is any work around to solve this problem.

A work-around is a separate (maybe virtual) "initialise" member
function, which will be called by the _user_ of your A or B class,
after creating the object. If you want that sequence (construct,
then initialise) to be executed without client's knowing about it,
you need a factory (or several).

V
 
D

David White

Hi,

A pure function is called in the base function constructor. It
generate a run time error: "pure virtual method called".

My problem is that class A have some derived classes. I want A's
constructor change its behaviour accounting to the derived class.

I tried to make A::fun() not pure virtual but virtual. It doesn't
generate any error. But A::fun() is called in A's construction, while
I want B::fun() be called. I just don't want to define a default
virtual function.

I'm wondering if there is any work around to solve this problem.

Assuming that you might be constructing any derived class and that you want
to call the most derived class's fun(), and only once, and you want to call
it from a constructor, the following illustrates a (not entirely
satisfactory) workaround:

class A
{
public:
A(int) { /* stuff */ }
virtual void fun() = 0;
};

class B : public A
{
public:
B() { fun();/* other stuff */ }
void fun();
protected:
B(int) { /* other stuff */ }
};

class C : public B
{
public:
C() : B(int) { fun();/* other stuff */ }
void fun();
protected:
C(int) : B(int) { /* other stuff */ }
};

class D : public C
{
public:
D() : C(int) { fun();/* other stuff */ }
void fun();
protected:
D(int) : C(int) { /* other stuff */ }
};

And so on...

DW
 
D

David White

David said:
class A
{
public:
A(int) { /* stuff */ }
virtual void fun() = 0;
};

[snip]

Sorry, rushed that a bit. Try this instead:

class A
{
public:
A() { /* stuff */ }
virtual void fun() = 0;
};

class B : public A
{
public:
B() { fun();/* other stuff */ }
void fun();
protected:
B(int) { /* other stuff */ }
};

class C : public B
{
public:
C() : B(0) { fun();/* other stuff */ }
void fun();
protected:
C(int) : B(0) { /* other stuff */ }
};

class D : public C
{
public:
D() : C(0) { fun();/* other stuff */ }
void fun();
protected:
D(int) : C(0) { /* other stuff */ }
};

And so on...

DW
 
P

Peter

Hi,

A pure function is called in the base function constructor. It generate
a run time error: "pure virtual method called".

My problem is that class A have some derived classes. I want A's
constructor change its behaviour accounting to the derived class.

I tried to make A::fun() not pure virtual but virtual. It doesn't
generate any error. But A::fun() is called in A's construction, while I
want B::fun() be called. I just don't want to define a default virtual
function.
Yes, if you try to call B::fun(), you should define a explicit
constructor to invoke it. Since class B like you've wrote has no
constructor, compiler will sythesize a default construtor to invoke
A:A() for you. that wouldn't invoke B:fun() at all. Doing that is your
responsibility not compiler.
I'm wondering if there is any work around to solve this problem.

Best wishes,
Peng


#include <iostream>

class A{
public:
A(){ fun();}
virtual void fun() = 0;
};

class B : public A{
public:
virtual void fun(){
std::cout << __PRETTY_FUNCTION__ << std::endl;
}
};

int main(int argc, char *argv[])
{
B b;
}
 
A

AnonMail2005

When a well respected expert such as Meyers includes item #9
in his Effectice C++, Third Edition, titled "Never call a virtual
function during construction or destruction", you have to have
to have a very good reasons to do it :). That book should be
read by every C++ programmer.

Sutter and Alexandrescu's C++ Coding Standards item #49 gives an
example of how to get around this issue by using an initialize
function.
 
A

Alf P. Steinbach

* (e-mail address removed):
My problem is that class A have some derived classes. I want A's
constructor change its behaviour accounting to the derived class.

That's FAQ item 23.4, e.g. at
<url: http://www.parashift.com/c++-faq-lite/strange-inheritance.html#faq-23.4>

(I often answer this question because I argued hard to get that into the FAQ,
so it's sort of 50% "my" item even though the wording is Marshall's...)

(But do people point to the FAQ anyway? No, they either don't understand the
problem, perhaps because of hasty reading of the news article, like Peter, or
give for once in a million Bad Advice, like Victor (sorry, but it was really
bad) did this time, it's very rare but happens, also for me, or give bad
advice with an Appeal To Authority fallacy added on top, like the anonymous
AnonMail. I hope people will point more to the FAQ, both because it reduces
discussion that can muddy waters, and because it helps people find the FAQ.)
 
A

Alf P. Steinbach

* Victor Bazarov:
What you're trying to accomplish goes against a very basic principle:
member functions shall not be called for an object whose construction
hasn't completed. If you're trying to call B::fun from A::A, the B
object hasn't finished constructing. Java is notoriously bad about
this particular behaviour and it is a constant cause of trouble.


A work-around is a separate (maybe virtual) "initialise" member
function, which will be called by the _user_ of your A or B class,
after creating the object.

Don't do that: it allows for zombie objects, double init and whatnot.

See FAQ item 23.4.

If you want that sequence (construct,
then initialise) to be executed without client's knowing about it,
you need a factory (or several).

Nope.
 
R

Richard Herring

Alf P. Steinbach said:
* (e-mail address removed):

That's FAQ item 23.4, e.g. at
<url: http://www.parashift.com/c++-faq-lite/strange-inheritance.html#faq-23.4>

You mean the item that's moved to 23.5 (and 23.6) ? ;-)

http://www.parashift.com/c++-faq-lite/strange-inheritance.html#faq-23.5
http://www.parashift.com/c++-faq-lite/strange-inheritance.html#faq-23.6
(I often answer this question because I argued hard to get that into the FAQ,
so it's sort of 50% "my" item even though the wording is Marshall's...)

(But do people point to the FAQ anyway? No, they either don't understand the
problem, perhaps because of hasty reading of the news article, like Peter, or
give for once in a million Bad Advice, like Victor (sorry, but it was really
bad) did this time, it's very rare but happens, also for me, or give bad
advice with an Appeal To Authority fallacy added on top, like the anonymous
AnonMail.

.... or point to the wrong FAQ ;-(
 
R

Richard Herring

Alf P. Steinbach said:
* Richard Herring:

The FAQ numbering changed after my posting. Don't be such a whiner. ;-)
OK, I'll leave that to everyone you've contradicted in this thread ;-)
 

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

Forum statistics

Threads
473,768
Messages
2,569,575
Members
45,053
Latest member
billing-software

Latest Threads

Top