首页 > 解决方案 > 从派生构造函数调用受保护的构造函数

问题描述

我有一个带有受保护构造函数的基类,因为不应直接实例化此类。

    class Transform {
      protected:
        Transform();
        ~Transform() {}

      public:
        glm::vec3 some_member;  // value will be initialized in the constructor
        ...  // many other members
    }

然后我有很多派生类

    class Camera : public Transform {
      public:
        Camera();
        ...
    }
    class Light: public Transform {
      public:
        Light();
        ...
    }

我很惊讶派生构造函数中默认不调用基类构造函数,我认为它会被自动调用,结果证明是错误的。所以现在我想显式调用基类构造函数,以便正确初始化基类成员,所以我尝试了:

    Camera::Camera() {
        Transform::Transform();  // error C2248: cannot access protected member
        __super::Transform();  // error C2248: cannot access protected member
    }

基本构造函数是受保护的,不是私有的,为什么我不能在派生类中访问它?

神奇的是,我发现这很好用,但我不明白为什么,这里有什么区别?

    Camera::Camera() : Transform() {  // compile successfully
        ...
    }

标签: c++

解决方案


我很惊讶在派生构造函数中默认不调用基类构造函数

如果基类有一个适用的构造函数,那么它将被调用。如果没有适用的构造函数,则必须显式调用它,否则派生的构造函数将是格式错误的。

一些例子:

class Base1 {
protected:
    Base1() {}
};

struct Derived1 : Base1 {
    Derived1() {} // calls the base constructor
};

class Base2 {
protected:
    Base2(int) {}
};

struct Derived2a : Base2 {
    Derived2a() {} // ill-formed
};


struct Derived2b : Base2 {
    Derived2b() : Base2(42) {} // explicit call
};

基本构造函数是受保护的,不是私有的,为什么我不能在派生类中访问它?

您可以访问构造函数。无论访问如何,您都不能在函数体内调用任何构造函数。

如果要显式调用基本构造函数(在默认构造函数的情况下不需要这样做),则必须使用成员初始化程序列表。尽管有名字,但它是基础子对象与成员子对象一起初始化的地方。

神奇的是,我发现这很好用,但我不明白为什么,这里有什么区别?

不同之处在于您使用的是成员初始化列表,这是初始化基的位置。没有魔法。


推荐阅读