Calling virtual functions inside constructors

前端 未结 13 1040

Suppose I have two C++ classes:

class A
{
public:
  A() { fn(); }

  virtual void fn() { _n = 1; }
  int getn() { return _n; }

protected:
  int _n;
};

clas         


        
13条回答
  •  借酒劲吻你
    2020-11-21 06:12

    Other answers have already explained why virtual function calls don't work as expected when called from a constructor. I'd like to instead propose another possible work around for getting polymorphic-like behavior from a base type's constructor.

    By adding a template constructor to the base type such that the template argument is always deduced to be the derived type it's possible to be aware of the derived type's concrete type. From there, you can call static member functions for that derived type.

    This solution does not allow non-static member functions to be called. While execution is in the base type's constructor, the derived type's constructor hasn't even had time to go through it's member initialization list. The derived type portion of the instance being created hasn't begun being initialized it. And since non-static member functions almost certainly interact with data members it would be unusual to want to call the derived type's non-static member functions from the base type's constructor.

    Here is a sample implementation :

    #include 
    #include 
    
    struct Base {
    protected:
        template
        explicit Base(const T*) : class_name(T::Name())
        {
            std::cout << class_name << " created\n";
        }
    
    public:
        Base() : class_name(Name())
        {
            std::cout << class_name << " created\n";
        }
    
    
        virtual ~Base() {
            std::cout << class_name << " destroyed\n";
        }
    
        static std::string Name() {
            return "Base";
        }
    
    private:
        std::string class_name;
    };
    
    
    struct Derived : public Base
    {   
        Derived() : Base(this) {} // `this` is used to allow Base::Base to deduce T
    
        static std::string Name() {
            return "Derived";
        }
    };
    
    int main(int argc, const char *argv[]) {
    
        Derived{};  // Create and destroy a Derived
        Base{};     // Create and destroy a Base
    
        return 0;
    }
    

    This example should print

    Derived created
    Derived destroyed
    Base created
    Base destroyed
    

    When a Derived is constructed, the Base constructor's behavior depends on the actual dynamic type of the object being constructed.

提交回复
热议问题