C++ Virtual Function from Constructor

Calling virtual functions inside constructors

Calling virtual functions from a constructor or destructor is dangerous and should be avoided whenever possible. All C++ implementations should call the version of the function defined at the level of the hierarchy in the current constructor and no further.

The C++ FAQ Lite covers this in section 23.7 in pretty good detail. I suggest reading that (and the rest of the FAQ) for a followup.

Excerpt:

[...] In a constructor, the virtual call mechanism is disabled because overriding from derived classes hasn’t yet happened. Objects are constructed from the base up, “base before derived”.

[...]

Destruction is done “derived class before base class”, so virtual functions behave as in constructors: Only the local definitions are used – and no calls are made to overriding functions to avoid touching the (now destroyed) derived class part of the object.

EDIT Corrected Most to All (thanks litb)

Calling a virtual function from the constructor

And I'm wondering if mine code is fine even if it breaks this rule:

It depends on what you mean by "fine". Your program is well-formed, and its behavior is well-defined, so it won't invoke undefined behavior and stuff like that.

However, one may expect, when seeing a call to a virtual function, that the call is resolved by invoking the implementation provided by the most derived type which overrides that function.

Except that during construction, the corresponding sub-object has not been constructed yet, so the most derived subobject is the one currently being constructed. Result: the call is dispatched as if the function were not virtual.

This is counter-intuitive, and your program should not rely on this behavior. Therefore, as a literate programmer, you should get used to avoid such a pattern and follow Scott Meyer's guideline.

Is it bad practice to call a virtual function from constructor of a class that is marked final

Regarding

Normally calling virtual functions from constructors is considered bad practice, because overridden functions in sub-objects will not be called as the objects have not been constructed yet.

That is not the case. Among competent C++ programmers it’s normally not regarded as bad practice to call virtual functions (except pure virtual ones) from constructors, because C++ is designed to handle that well. In contrast to languages like Java and C#, where it might result in a call to a method on an as yet uninitialized derived class sub-object.

Note that the dynamic adjustment of dynamic type has a runtime cost.

In a language oriented towards ultimate efficiency, with "you don't pay for what you don't use" as a main guiding principle, that means that it's an important and very much intentional feature, not an arbitrary choice. It's there for one purpose only. Namely to support those calls.


Regarding

In this case class derived is marked as final so no o further sub-objects can exist. Ergo the virtual call will resolve correctly (to the most derived type).

The C++ standard guarantees that at the time of construction execution for a class T, the dynamic type is T.

Thus there was no problem about resolving to incorrect type, in the first place.


Regarding

Is it still considered bad practice?

It is indeed bad practice to declare a member function virtual in a final class, because that’s meaningless. The “still” is not very meaningful either.

Sorry, I didn't see that the virtual member function was inherited as such.

Best practice for marking a member function as an override or implementation of pure virtual, is to use the keyword override, not to mark it as virtual.

Thus:

void startFSM() override
{ theFSM_.start(); }

This ensures a compilation error if it is not an override/implementation.

C++ virtual function in constructor

There is no difference. That's the danger.

If you did not know better then you might expect this instead:

Derived Class print_it
Derived Class print_it

The expectation is there because if you call the virtual print_it() from functions in Base, polymorphism means you'll usually get the Derived version instead.

But, when you write it in the Base constructor, the Base part of the object is still under construction, and the "dynamic type" of the object under construction is still Base, not Derived. So you do not get the usual polymorphic behaviour.

The article is warning you about this fact.

C++ virtual function from constructor

Because base is constructed first and hasn't "matured" into a derived yet. It can't call methods on an object when it can't guarantee that the object is already properly initialized.

C++ Calling final virtual function in constructor

Is calling virtual final function in constructing/destructing phase is
allowed in C++ standard?

Calling a virtual function during construction/destruction is well defined and completely legal except in the case of pure virtual functions.

Calling virtual function in constructor and destructor is forbidden

I don't know (nor cares) who says it's "bad" or "forbidden" from a stylistic point of view, code maintenance point of view... The ability to maintain code depends first on knowing the relevant language and tools well; not knowing what virtual calls do during these phases (*) will lead to misunderstand on the part of the maintainers which is fixed by selecting more experienced maintainers and not dumbing down the programming style.

(*) which aren't technically part of the "lifetime" of the object, which isn't even a very useful concept as objects are usable and used in their constructor (before their lifetime has started) in any non trivial program (I think the standard should simply suppress this unneeded concept).

accessing to subclass' variable, not initialized yet, can occur in
overridden version of virtual function, which is declared in the
subclass.

It can't. During construction of a base class subobject B (say by constructor B::B()), the type of the object is being constructed is by definition B.

overridden version of virtual function, which is declared in the
subclass.

No, there is no existing subclass object at that point, so there is no overriding.

While virtual final function is not, it's final and there's no way to
access to subclass' variables.

It makes no difference.

The dynamic type of a polymorphic object is established by a constructor, after the constructors for base classes and before constructing members.

If so, is it widely implemented to most C++ compilers?

In practice all compilers implement setting the dynamic type of an object by changing the one or many vtable pointers to point to appropriate vtables for the type; that is done as part of construction.

It means that during construction, the vptr value changes as derived objects are constructed.

Virtual member call in a constructor

When an object written in C# is constructed, what happens is that the initializers run in order from the most derived class to the base class, and then constructors run in order from the base class to the most derived class (see Eric Lippert's blog for details as to why this is).

Also in .NET objects do not change type as they are constructed, but start out as the most derived type, with the method table being for the most derived type. This means that virtual method calls always run on the most derived type.

When you combine these two facts you are left with the problem that if you make a virtual method call in a constructor, and it is not the most derived type in its inheritance hierarchy, that it will be called on a class whose constructor has not been run, and therefore may not be in a suitable state to have that method called.

This problem is, of course, mitigated if you mark your class as sealed to ensure that it is the most derived type in the inheritance hierarchy - in which case it is perfectly safe to call the virtual method.

C++ Calling Virtual Method in Constructor

shoudn't I call a virtual method in the constructor?

Doing so will call the override in the class being constructed, not necessarily the final override. This is probably not what you want, and an error if the function is pure virtual in the current class, so generally you shouldn't.

In this case, the error suggests that it's pure virtual, and not implemented, in this class, so calling it is definitely an error. Luckily, it gave you a reasonably friendly linker error rather than undefined runtime behaviour. (UPDATE: the code you've posted confirms that guess - you can't call the function from the constructor).

Is there way to solve this problem

Many problems can be solved with an extra level of indirection. I would implement the heuristic in a separate delegate class, rather than a subclass:

struct Heuristic {
virtual ~Heuristic() {} // Don't forget this on a polymorphic base class
virtual int calculateUtility() = 0;
virtual int calculateUtility( Node* ) = 0;
};

class HeuristicSearch: public BruteSearch {
public:
HeuristicSearch(Heuristic & h, int initial[BOARD_LIMIT][BOARD_LIMIT]) :
BruteSearch(initial),
heuristic(h),
utilityCost(heuristic.calculateUtility()) // No problem calling this
{}

private:
Heuristic & heuristic;
int utilityCost;
// and so on
};

The delegate is fully constructed before we start to construct the Search class, so there are no issues accessing it from the constructor.

Alternatively, to avoid unnecessary runtime polymorphism, I might inject the delegate type as a template parameter:

template <class Heuristic>
class HeuristicSearch: public BruteSearch {
public:
HeuristicSearch(int initial[BOARD_LIMIT][BOARD_LIMIT]) :
BruteSearch(initial),
utilityCost(heuristic.calculateUtility()) // Doesn't have to be virtual
{}

private:
Heuristic heuristic;
int utilityCost;
// and so on
};


Related Topics



Leave a reply



Submit