Calling virtuals inside constructors

This is a discussion on Calling virtuals inside constructors within the C++ Programming forums, part of the General Programming Boards category; Hi all, I know you shouldnt use virtual functions inside constructors because the vtable has yet to be constructed. However ...

  1. #1
    Registered User
    Join Date
    Oct 2004
    Posts
    100

    Calling virtuals inside constructors

    Hi all,

    I know you shouldnt use virtual functions inside constructors because the vtable has yet to be constructed. However I have come across a problem which im convinced is a common problem so Im hoping there is a well known way to solve it.

    Code:
    class A
    {
    public:
       A( ) { Init() ; }
      virtual void Init() = 0 ;
    };
    
    class B : public A
    {
    public:
     virtual void Init() {}
    };
    So if class A is my base class which requires all derived classes to implement function Init and then to make sure Init is never forgotten to be called it calls Init from its own constructor. Now I know the above code will not work because before B is constructed it constructs A so there is no way that A can call B's version of Init because the vtable hasnt been setup.

    Is there a way to solve the above problem so that it is gaurenteed than anything that derives from class A will always be initialized on construction?

    Thanks for any help

  2. #2
    C++ Witch laserlight's Avatar
    Join Date
    Oct 2003
    Location
    Singapore
    Posts
    21,662
    I do not think that there is a solution, and I also think that requiring that derived classes implement an Init member function instead of having the option to directly initialise in the constructor is not necessarily a good thing.
    C + C++ Compiler: MinGW port of GCC
    Version Control System: Bazaar

    Look up a C++ Reference and learn How To Ask Questions The Smart Way

  3. #3
    Registered User
    Join Date
    Oct 2004
    Posts
    100
    Thanks for the reply :-)

    Quote Originally Posted by laserlight View Post
    and I also think that requiring that derived classes implement an Init member function instead of having the option to directly initialise in the constructor is not necessarily a good thing.
    Can you explain what you mean by that please?

  4. #4
    Kernel hacker
    Join Date
    Jul 2007
    Location
    Farncombe, Surrey, England
    Posts
    15,677
    I think what Laserlight is saying is that since A() calls Init, which is not valid if B does not in itself implement an Init. You should have a minimal (empty) Init() inside the A class.

    Further, the "solution" to calling virtual functions in the constructor is to not call them from the constructor - a two-stage construction is needed, where you construct the class first, then call the Init() AFTER the class has been constructed. You may want to have some sort of checking mechanism (in debug builds at least) that checks that Init is called on the constructed object before it is being used - e.g. set a bool initialized to true when Init ends (at the end in case of exceptions during the "middle" part).

    --
    Mats
    Compilers can produce warnings - make the compiler programmers happy: Use them!
    Please don't PM me for help - and no, I don't do help over instant messengers.

  5. #5
    The larch
    Join Date
    May 2006
    Posts
    3,573
    You might consider something like:

    Code:
    class A
    {
    public:
       A( ) {}
    };
    
    class B : public A
    {
      void Init() {}
    public:
      B() { Init(); }
    };
    Now you cannot guarantee that all constructors use an Init method but it is not clear to me why this should be mandatory. The purpose of constructors is to initialize the class itself but this can be done in various ways. Also each base class initalizes itself in its constructor, rather than attempt to initialize its descendants.

    That or use two-stage constructor if an Init() method is really needed.
    I might be wrong.

    Thank you, anon. You sure know how to recognize different types of trees from quite a long way away.
    Quoted more than 1000 times (I hope).

  6. #6
    Registered User
    Join Date
    Jun 2005
    Posts
    6,266
    Quote Originally Posted by matsp View Post
    I think what Laserlight is saying is that since A() calls Init, which is not valid if B does not in itself implement an Init. You should have a minimal (empty) Init() inside the A class.
    My interpretation is different. The base class and derived class constructors should just do the work of initialisation. Then it is up to the programmer to decide, for each class, how that is achieved. But calling a virtual function is not one of the preferred options.
    Quote Originally Posted by matsp View Post
    Further, the "solution" to calling virtual functions in the constructor is to not call them from the constructor - a two-stage construction is needed, where you construct the class first, then call the Init() AFTER the class has been constructed.
    That's actually quite hideous in practice: too many opportunities for the programmer to forget to call the Init() function or (sometimes worse) to call it more than once.

    Quote Originally Posted by matsp View Post
    You may want to have some sort of checking mechanism (in debug builds at least) that checks that Init is called on the constructed object before it is being used - e.g. set a bool initialized to true when Init ends (at the end in case of exceptions during the "middle" part).
    That's just a hack to get around a design that is flawed anyway.
    Right 98% of the time, and don't care about the other 3%.

  7. #7
    Kernel hacker
    Join Date
    Jul 2007
    Location
    Farncombe, Surrey, England
    Posts
    15,677
    I'm by no means saying that two-stage construction is actually a "good" idea. It is a solution that can be used if it's required, but I agree, there's probably something a bit wrong with the design if you need to do that. I should have made that clearer in my original post.

    And if you HAVE to use this method, then I still think it's a good idea to have checks to DETECT the programmer getting it wrong - Init() can also check the bool variable to spot multiple Init calls - but that is indeed a bandage holding the wheel in place, and a better solution would be to design out the need to do this sort of thing. There are several solutions to the problem - the simplest one is to simply not make Init() a virtual function, but let each class that feels a need to have one have it's own private Init() function - the base class's Init function will be called by the base-class constructor, which is automatically called by the derived constructor.

    There may be situations when there is a GENUINE need to call a virtual function of a derived class from the base-class during some sort of post-construction initialization, but in general, it's probably WRONG when this is happening.

    --
    Mats
    Compilers can produce warnings - make the compiler programmers happy: Use them!
    Please don't PM me for help - and no, I don't do help over instant messengers.

  8. #8
    C++ Witch laserlight's Avatar
    Join Date
    Oct 2003
    Location
    Singapore
    Posts
    21,662
    What I meant was that I believe that constructors should be used to perform initialisation. Sure, sometimes it makes sense to delegate some of the work to a helper function, but that would depend on the situation. I am not in favour of two phase construction if it can be avoided.
    C + C++ Compiler: MinGW port of GCC
    Version Control System: Bazaar

    Look up a C++ Reference and learn How To Ask Questions The Smart Way

  9. #9
    and the hat of sweating
    Join Date
    Aug 2007
    Location
    Toronto, ON
    Posts
    3,545
    One other thing that should work would be to create a function that creates an object of the type you want and then calls Init() on it and returns that object. You could even make it a static member variable called something like CreateObj() and make the constructors private to force people to use the CreateObj() function if they want an instance of the class... I believe that's the Factory design pattern.
    "I am probably the laziest programmer on the planet, a fact with which anyone who has ever seen my code will agree." - esbo, 11/15/2008

    "the internet is a scary place to be thats why i dont use it much." - billet, 03/17/2010

  10. #10
    Registered User
    Join Date
    May 2007
    Posts
    147
    cpjust, that's what I was thinking.

    It's a design pattern called "factory" or "object factory".

    It includes the notion that constructors should not be public, so the only way to create such objects is through the factory, and that leaves the factory responsible for complete construction of an object.

  11. #11
    Registered User
    Join Date
    Jun 2005
    Posts
    6,266
    Quote Originally Posted by cpjust View Post
    One other thing that should work would be to create a function that creates an object of the type you want and then calls Init() on it and returns that object. You could even make it a static member variable called something like CreateObj() and make the constructors private to force people to use the CreateObj() function if they want an instance of the class...
    The downside of that is that the CreateObj function needs to be modified every time you introduce a new class to the hierarchy .... specifically, the part of the function that creates the object. It also doesn't necessarily work all that cleanly unless the objects are created dynamically (eg with operator new).

    Easier to just put the logic into constructors, and create an object of required type.
    Quote Originally Posted by cpjust View Post
    I believe that's the Factory design pattern.
    What you describe is not the factory design pattern. Although it is true that a function who's purpose is to create objects is often called a "factory method" or "factory function".
    Right 98% of the time, and don't care about the other 3%.

Popular pages Recent additions subscribe to a feed

Similar Threads

  1. Still battling with Copy Control
    By Mario F. in forum C++ Programming
    Replies: 9
    Last Post: 06-23-2006, 08:04 AM
  2. Dikumud
    By maxorator in forum C++ Programming
    Replies: 1
    Last Post: 10-01-2005, 06:39 AM
  3. Using bitset class inside another
    By Dhekke in forum C++ Programming
    Replies: 3
    Last Post: 07-26-2005, 06:50 AM
  4. Function Calling From A DLL In a DLL
    By (TNT) in forum Windows Programming
    Replies: 1
    Last Post: 06-03-2002, 08:27 AM
  5. Calling on Base constructors..help please!!
    By incognito in forum C++ Programming
    Replies: 10
    Last Post: 01-08-2002, 05:17 PM

1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21