从派生类访问基类中的受保护成员
Posted
技术标签:
【中文标题】从派生类访问基类中的受保护成员【英文标题】: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 你说得对,我要我的披萨! :) 【参考方案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()
不初始化数据成员 date
和 year
这个默认构造函数在创建对象派生时被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
未初始化,并对其执行了左值到右值的转换。以上是关于从派生类访问基类中的受保护成员的主要内容,如果未能解决你的问题,请参考以下文章