为啥我不能访问派生构造函数的成员初始化列表中继承的受保护字段?

Posted

技术标签:

【中文标题】为啥我不能访问派生构造函数的成员初始化列表中继承的受保护字段?【英文标题】:Why can't I access inherited protected fields in a derived constructor's member initialization list?为什么我不能访问派生构造函数的成员初始化列表中继承的受保护字段? 【发布时间】:2020-11-19 18:40:00 【问题描述】:

我是 OOP 的新手。我最近在 C++ 中学习了一些关于继承的知识,protected 字段不能从类外部访问,但可以在继承类中访问。我的代码有一些问题,我不明白出了什么问题:

class Base

protected:
    int x;
    int y;
    int z;
public:
    Base(int a, int b): x(a), y(b)  cout << "Base constructor" << endl; ;
    Base(const Base& prev) : x(prev.x), y(prev.y)  cout << "Base copy constructor" << endl; ;

    void print_x()
    
        cout << x << endl;
    

    void print_y()
    
        cout << y << endl;
    

    ~Base()  cout << "Base destructor" << endl; ;
;

class Derived : public Base

public:
    Derived(int a, int b): x(a), y(b)  cout << "Derived constructor" << endl; ;    ////////ERROR : Class 
 'Derived' does not have any fields named 'x' and 'y'
;

int main()

    Base* b = new Base(10, 20);
    Derived* d = new Derived(10, 20);
    delete b;
    delete d;
    return 0;

如果Derived继承Base,为什么编译器会说Derived没有xy这两个字段?

【问题讨论】:

【参考方案1】:

你可以在Derived中访问它们,但是它们是Base的成员,不能直接在Derived的成员初始化列表中初始化。如果他们是public,这也行不通。注意Base类在Derived的成员初始化之前初始化。

要初始化base,可以在Derived的成员初始化列表中调用它的构造函数:

class Derived : public Base

  public:
      Derived(int a, int b) : Base(a, b)    ; 
;

更多详情请看这里:https://en.cppreference.com/w/cpp/language/constructor

PS:请注意,关于成员初始化列表,与基中 private 的成员也没有区别。基类的所有成员都是继承的,并在派生类的成员初始化之前进行初始化。

您错过了初始化z,在您的示例中没有理由使用newdelete。如果您修复上述问题,您将获得与此代码相同的输出:

int main()

    Base b(10,20);
    Derived d(10,20);

最后但同样重要的是,如果您打算多态地使用Derived,您需要将Base 的析构函数声明为virtual

【讨论】:

多态使用是什么意思? @Robert 我的意思是Base* b = new Derived(); 在这种情况下你不能在Base 中没有虚拟析构函数的情况下调用delete b; @Robert 即使你现在不这样做,迟早会有人这样做,所以当你公开继承时最好有一个虚拟析构函数 哦!我明白了.. 运行时多态是这样的吗? @Robert 是的。如果您不打算使用它,您也可以私有继承或使用组合

以上是关于为啥我不能访问派生构造函数的成员初始化列表中继承的受保护字段?的主要内容,如果未能解决你的问题,请参考以下文章

C++基类和派生类的构造函数

C#中继承类为啥可以通过属性访问基类的私有字段。

继承对基类私有数据成员的访问(在派生类中继承基类成员函数)

C ++:如何在派生类中定义基类构造函数,如果基构造函数具有带有私有成员的初始化列表[重复]

JavaScript中继承的实现方式

JavaScript中继承的实现方式