您完全正确,Parent::main() 无法访问Child::data,并且对任何神秘的info2 类型一无所知;对它来说,Parent::data 就是它的全部,info 是它的类型。
有一些简单的方法可以让Child::main() 与Child::data 一起工作而不是Parent::data,或者让它从每个版本访问所需的字段,但我怀疑这不是你想要的。如果您希望Parent 和Child 看到相同的data(分别作为info 和info2),那么data 本身应该多态使用。对于这个例子,为了简单起见,我将使用常规指针(反过来,operator. 将被替换为 operator->,当访问 data 的成员时),但我建议查看智能指针,例如 @ 987654340@来简化内存管理。
class Parent
{
public:
struct info
{
int a;
// Chances are, it's going to be deleted through an info* no matter what it is. Therefore, virtual destructor.
virtual ~info() = default;
};
info* data; // Consider using a smart pointer here, like std::unique_ptr.
virtual void main(void);
virtual void output() const; // Just adding this for convenience.
// Default constructor now allows data to be supplied, or creates it if necessary.
Parent(info* dp = nullptr) : data(dp ? dp : new info) {}
// Correct destructor will always be called.
virtual ~Parent() { if(data) { delete data; } }
};
void Parent::main()
{
data->a =1;
}
我们现在删除字段Child::data,而是让Child 将其所需的data 提供给Parent 的构造函数。
class Child: public Parent
{
public:
struct info2: public info
{
int b;
};
//info2 data;
virtual void main(void);
void output() const override; // Just adding this for convenience.
Child() : Parent(new info2) {}
};
Child 将在需要时将data 视为info2 而不是info。
void Child::main(void)
{
Parent::main();
auto dataPtr = static_cast<info2*>(data); // In Child, we know data is an info2*.
dataPtr->b = 2;
// Just gonna move these to output(), for a cleaner illustration.
//std::cout << "Data->a: " << data->a << "\n";
//std::cout << "Data->b: " << dataPtr->b << "\n";
}
这将导致 data 按需要工作,Parent 和 Child 都具有正确的类型。
void Parent::output() const {
std::cout << "Parent:\n";
std::cout << "> Data->a: " << data->a << "\n";
}
void Child::output() const /*override*/ {
std::cout << "Child as ";
Parent::output();
auto dataPtr = static_cast<info2*>(data);
std::cout << "Child:\n";
std::cout << "> Data->a: " << dataPtr->a << "\n";
std::cout << "> Data->b: " << dataPtr->b << "\n";
}
这将按预期执行,如 live on Coliru 所示。请注意,例如,如果您希望能够从预先存在的 Parent 创建一个 Child,您需要添加一个移动构造函数,该构造函数可以从一个 info 创建一个 info2;您应该考虑遵循Rule of Five,或者使用智能指针而不是原始指针。 ;P