Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

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

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.

But, Consider the following classes:

class base
{
public:
   base() {}
   ~base() {}

private:
   virtual void startFSM() = 0;
};

class derived final : public base
                    , public fsm_action_interface
{
public:
    derived() : base{}
              , theFSM_{}
    {  startFSM(); }


    /// FSM interface actions

private:
   virtual void startFSM()
   { theFSM_.start(); }

private:
    SomeFSMType theFSM_;
}

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

Is it still considered bad practice?

like image 272
mark Avatar asked Jun 30 '14 17:06

mark


People also ask

Can we call a virtual function from a constructor?

You can call a virtual function in a constructor, but be careful. It may not do what you expect. 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”.

When should you not call a virtual member function?

15 Answers. Show activity on this post. 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.

Why is it not acceptable to call a virtual method from the constructor of an abstract class?

Calling virtual functions in constructors makes your code extremely sensitive to the implementation details in derived classes. You can't control what derived classes do. Code that calls virtual functions in constructors is very brittle.

Why should calls to virtual functions be avoided in constructors and destructors?

As a general rule, you should never call virtual functions in constructors or destructors. If you do, those calls will never go to a more derived class than the currently executing constructor or destructor. In other words, during construction and destruction, virtual functions aren't virtual.


1 Answers

This would still be considered bad practice as this sort of this almost always indicates bad design. You'd have to comment the heck out of the code to explain why this works in this one case.

T.C.'s comment above reinforces one of the reasons why this is considered bad practice.

What happens if, a year down the line, you decide that derived shouldn't be final after all?

That said, in the example above, the pattern will work without issue. This is because the constructor of the most derived type is the one calling the virtual function. This problem manifests itself when a base class's constructor calls a virtual function that resolves to a subtype's implementation. In C++, such a function won't get called, because during base class construction, such calls will never go to a more derived class than that of the currently executing constructor or destructor. In essence, you end up with behavior you didn't expect.

Edit:

All (correct/non-buggy) C++ implementations have to 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.

Scott Meyers also weighs in on the general issue of calling virtual functions from constructors and destructors in Effective C++ Item 9

like image 87
bstar55 Avatar answered Sep 28 '22 08:09

bstar55