我正在一个项目中,我有一系列子类。 我想从数组中调用一个重写的子函数,但是它调用了父函数。
#include <iostream>
class Parent {
public:
Parent(){}
void print() {
std::cout << "I'm the parent!" << std::endl;
}
};
class ChildOne : public Parent {
public:
ChildOne(){}
void print() {
std::cout << "I'm childOne!" << std::endl;
}
};
class ChildTwo : public Parent {
public:
ChildTwo() {}
void print() {
std::cout << "I'm childTwo!" << std::endl;
}
};
int main(int argc, char const *argv[]) {
Parent arr[] = {ChildOne(), ChildTwo()};
int n = 2;
for(int i = 0; i < n; i++) {
arr[i].print();
}
return 0;
}
我得到的输出是
I'm the parent!
I'm the parent!
我想要的输出是
I'm childOne!
I'm childTwo!
答案 0 :(得分:3)
将实例存储在该类型数组中时,您将隐式将所有实例强制转换为类型Parent
。由于您使用的是静态分派,因此您总是要使用(隐式)向下转换为的基本类型来调用该方法。
答案 1 :(得分:2)
您的代码遇到两个问题:
您实际上根本没有覆盖print()
,因为它不是virtual
。因此,您只是在每个子类中超载,隐藏父类的方法。
将它们存储到数组中时,您是slicing your objects。因此,print()
是否为虚拟并不重要,因为数组中没有子对象,只有父对象。仅当使用对基类的指针/引用时,多态性才能正常工作。
尝试以下方法:
#include <iostream>
class Parent {
public:
Parent(){}
virtual void print() {
std::cout << "I'm the parent!" << std::endl;
}
};
class ChildOne : public Parent {
public:
ChildOne(){}
void print() override {
std::cout << "I'm childOne!" << std::endl;
}
};
class ChildTwo : public Parent {
public:
ChildTwo() {}
void print() override {
std::cout << "I'm childTwo!" << std::endl;
}
};
int main() {
ChildOne c1;
ChildTwo c2;
Parent* arr[] = {&c1, &c2};
int n = 2;
for(int i = 0; i < n; i++) {
arr[i]->print();
}
return 0;
}
答案 2 :(得分:2)
首先,Parent
的成员函数必须为virtual
。
class Parent
{
public:
Parent(){}
virtual void print() {std::cout << "I'm the parent!" << std::endl;};
};
然后,孩子需要覆盖它。在C ++ 11和更高版本中,建议使用override
class ChildOne : public Parent
{
public:
ChildOne(){}
void print() override {std::cout << "I'm childOne!" << std::endl;};
};
要解决的第二件事是您在main()
中的代码
Parent arr[] = {ChildOne(), ChildTwo()};
通过切片初始化两个Parent
对象,即arr[0]
和arr[1]
都是Parent
类型,而不是ChildOne
或ChildTwo
类型。
要解决此问题,arr
必须是一个指针数组,并进行相应的初始化。
Parent *arr[] = {new ChildOne(), new ChildTwo()};
,可以跟着
for(int i = 0; i < 2; i++)
{
arr[i]->print();
}
for(int i = 0; i < 2; i++) // to avoid a memory leak
{
delete arr[i];
}
// don't use elements of `arr` here
更好的方法(C ++ 11和更高版本)是编写main()
是使用标准标头std::unique_ptr
中的<memory>
std::unique_ptr<Parent> arr[] = {new ChildOne(), new ChildTwo()};
允许取消循环以释放arr
的元素。在C ++ 14和更高版本中,可以使用arr
创建std::make_unique()
中的对象。
答案 3 :(得分:1)
您需要将父函数指定为virtual
,子函数应使用override
关键字。
class Parent {
public:
Parent(){}
virtual void print() {
std::cout << "I'm the parent!" << std::endl;
}
};
class ChildOne : public Parent {
public:
ChildOne(){}
void print() override {
std::cout << "I'm childOne!" << std::endl;
}
};
class ChildTwo : public Parent {
public:
ChildTwo() {}
void print() override {
std::cout << "I'm childTwo!" << std::endl;
}
};