【问题标题】:Accessing protected member in base class from a derived class从派生类访问基类中的受保护成员
【发布时间】:2014-08-27 08:49:15
【问题描述】:

我有以下sn-p的代码:

const int DATE_LENGTH = 6;

class BaseClass {
    protected:
        int date[DATE_LENGTH];
        int year;
    public:
        BaseClass(){}
        BaseClass(int *d) {
            for (int i = 0; i < DATE_LENGTH; i++) { date[i] = d[i];}
            year = 1900 + date[4] * 10 + date[5];
        }
        void printYear() {
            cout << year << endl;
        }
};

class DerivedClass : public BaseClass {
    public:
        DerivedClass() {}
        void printYear() {
            cout << year << endl;
        }
};

int main(int argc, char *argv[]) {
    int dob[] = {1, 6, 1, 0, 9, 0};
    BaseClass base(dob);
    base.printYear(); // prints 1990

    DerivedClass derived;
    derived.printYear(); // prints 1439156608
}

我无法理解为什么派生类中printYear() 的输出会输出垃圾。我是否遗漏了一些非常明显的东西?

任何帮助将不胜感激!

【问题讨论】:

  • 你的默认构造函数不会初始化任何东西,所以你会得到内存中发生的任何东西。
  • @T.C.:这并不完全正确,基础子对象确实被初始化了。语言要求这种情况发生。只是选择了一个很差的初始化。
  • @RetiredNinja:这实际上不是你可以保证的。这是未定义的行为,你可能会从记忆中得到一些东西,或者披萨,或者丢掉工作。
  • 你可以从未定义的行为中得到比萨吗?全速前进!
  • @KerrekSB 你说得对,我要我的披萨! :)

标签: c++ class protected derived-class


【解决方案1】:

其他提供的答案仅处理部分问题,部分原因是 date 本身是 never 在 DerivedClass 默认构造函数中定义的当前提供,另一部分是 BaseClass 默认构造函数 still 没有为任一类变量(日期或年份)定义值。如果使用以下代码,取决于默认的日期和年份,DerivedClass 实际上不需要额外的更改。

#include <iostream>

using namespace std;

const int DATE_LENGTH = 6;

class BaseClass {
    protected:
        int date[DATE_LENGTH];
        int year;
    public:
        BaseClass()
        {
            int date[] = {1, 6, 1, 0, 9, 0};
            year = 1900 + date[4] * 10 + date[5];
        }
        BaseClass(int *d)
        {
            for (int i = 0; i < DATE_LENGTH; i++) { date[i] = d[i];}
            year = 1900 + date[4] * 10 + date[5];
        }
        void printYear() {
            cout << year << endl;
        }
};

class DerivedClass : public BaseClass {
    public:
        DerivedClass() {}
        void printYear() {
            cout << year << endl;
        }
};

int main(int argc, char *argv[])
{
    int dob[] = {1, 6, 1, 0, 9, 0};
    BaseClass base(dob);
    base.printYear(); // prints 1990

    DerivedClass derived;
    derived.printYear(); // prints 1439156608
    return 0;
}

应用程序输出

1990
1990

【讨论】:

    【解决方案2】:

    BaseClass的默认构造函数

    BaseClass(){}
    

    不初始化数据成员 dateyear

    这个默认构造函数在创建对象派生时被DerivedClass类的默认构造函数调用

    DerivedClass derived;
    

    因此,这些数据成员具有任意值,并且您的程序具有未定义的行为。

    通过以下方式更改派生类

    class DerivedClass : public BaseClass {
        public:
            using BaseClass::BaseClass;
            DerivedClass() {}
            void printYear() {
                cout << year << endl;
            }
    };
    

    并创建派生的对象

    DerivedClass derived( dob );
    

    或者代替 using 声明,您可以自己在 DerivedClass 类中显式定义一个构造函数,该构造函数具有一个 int * 类型的参数,并调用基类的相应构造函数。例如

    class DerivedClass : public BaseClass {
        public:
            DerivedClass() {}
            DerivedClass( int *d ) : BaseClass( d ) {}
            void printYear() {
                cout << year << endl;
            }
    };
    

    【讨论】:

      【解决方案3】:

      您的程序有未定义的行为。您正在使用的DerivedClass 的默认构造函数不会初始化year 成员。

      如果您想初始化基成员,可以通过调用适当的基构造函数或直接赋值来实现。

      DerivedClass() { year = 1999; }
      

      【讨论】:

      • 你确定这是 UB 并且不能只是未指定的值吗?
      • @Deduplicator,是的,year 未初始化,并对其执行了左值到右值的转换。
      猜你喜欢
      • 1970-01-01
      • 2019-01-20
      • 2012-08-29
      • 2016-04-07
      • 2018-11-27
      • 1970-01-01
      • 2018-04-17
      相关资源
      最近更新 更多