Can pure virtual function be called in base class constructor?

Discussion in 'C++' started by PengYu.UT@gmail.com, Oct 14, 2005.

  1. Guest

    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;
    }
     
    , Oct 14, 2005
    #1
    1. Advertising

  2. wrote:
    > 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
     
    Victor Bazarov, Oct 14, 2005
    #2
    1. Advertising

  3. David White Guest

    wrote:
    > 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
     
    David White, Oct 14, 2005
    #3
  4. David White Guest

    David White wrote:
    >
    > 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
     
    David White, Oct 14, 2005
    #4
  5. Peter Guest

    wrote:
    > 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;
    > }
     
    Peter, Oct 14, 2005
    #5
  6. Guest

    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.
     
    , Oct 14, 2005
    #6
  7. * :
    >
    > 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: Because it messes up the order in which people normally read text.
    Q: Why is it such a bad thing?
    A: Top-posting.
    Q: What is the most annoying thing on usenet and in e-mail?
     
    Alf P. Steinbach, Oct 14, 2005
    #7
  8. * Victor Bazarov:
    > wrote:
    > > 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.


    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.

    --
    A: Because it messes up the order in which people normally read text.
    Q: Why is it such a bad thing?
    A: Top-posting.
    Q: What is the most annoying thing on usenet and in e-mail?
     
    Alf P. Steinbach, Oct 14, 2005
    #8
  9. In message <>, Alf P. Steinbach
    <> writes
    >* :
    >>
    >> 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>


    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 ;-(

    >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.)
    >


    --
    Richard Herring
     
    Richard Herring, Oct 18, 2005
    #9
  10. * Richard Herring:
    > ... or point to the wrong FAQ ;-(


    The FAQ numbering changed after my posting. Don't be such a whiner. ;-)

    --
    A: Because it messes up the order in which people normally read text.
    Q: Why is it such a bad thing?
    A: Top-posting.
    Q: What is the most annoying thing on usenet and in e-mail?
     
    Alf P. Steinbach, Oct 18, 2005
    #10
  11. In message <>, Alf P. Steinbach
    <> writes
    >* Richard Herring:
    >> ... or point to the wrong FAQ ;-(

    >
    >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 ;-)

    --
    Richard Herring
     
    Richard Herring, Oct 18, 2005
    #11
    1. Advertising

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

It takes just 2 minutes to sign up (and it's free!). Just click the sign up button to choose a username and then you can ask your own questions on the forum.

Share This Page