好的,我有两节课。
class a{
public:
a(){};
void print(){cout << "hello"};
}
class b : public a{
public:
void print(){cout << "hello world";}
}
一群有孩子的父母
a blah[10];
blah[5] = b();
我打电话打印,并希望它说出你好世界。
blah[5].print();
但是它叫父母。我该如何解决这个问题?
答案 0 :(得分:11)
这可以通过声明虚函数来修复:la:
class a{
public:
virtual void print(){
cout << "hello";
}
}
class b : public a{
public:
virtual void print() {
cout << "hello world";
}
}
这就是在C ++中实现多态的方法。更多信息:http://en.wikipedia.org/wiki/Virtual_function
但是,应该注意的是,在您的示例中,它永远不会调用子函数,因为您使用的是对象值,而不是对象的指针/引用。要解决这个问题,
a * blah[10];
blah[5] = new b();
然后:
blah[5]->print();
答案 1 :(得分:3)
您正在寻找的是运行时多态,这意味着让对象采用“多种形式”(即a或b),并在程序运行时采取相应的行动。在C ++中,您可以通过在基类virtual
中创建函数a
来实现此目的:
virtual void print() {cout << "hello"};
然后,您需要通过指针或引用存储元素,并且 - 通常派生类可以引入新的数据成员并需要更多存储 - 使用new
在堆上创建对象是正常的:
a* blah[10];
blah[5] = new b();
然后你可以打电话:
blah[5]->print();
它会调用b
的{{1}}实现。
您应该稍后print()
(以及您指向delete blah[5]
返回的内存的任何其他内容。)
在实践中,最好使用一个容器,当容器本身被破坏时,可以删除它包含的对象,无论是由于留下范围还是被删除。 new
就是这样一个容器。您还可以使用智能指针自动删除std::vector<>
和a
对象。如果在b
语句执行之前抛出异常,并且您希望程序在不泄漏内存的情况下继续运行,这有助于使代码更正。 boost库是获取智能指针实现的最简单/最好的地方。一起:
delete
(使用带有#include <vector>
#include <boost/shared_ptr.hpp>
std::vector<boost::shared_pointer<a> > blah(10);
blah[5] = new b();
的向量更为正常,因为它会自动增长向量以适合您添加的所有元素,并通过调用push_back()
获得新的总数。)
答案 2 :(得分:0)
这样做是因为您告诉编译器您的实例属于a
类型。它位于a
个对象的数组中,对吗?所以它的类型为a
!
当然,您希望b
中的方法覆盖a
中的方法,尽管有父类型的引用。您可以在父类的函数声明中使用virutal
关键字来获取该行为。
virtual void print(){cout << "hello"};
为什么会这样?
因为当您将对象转换为父类时,您引入了歧义。调用此对象的print()
时,我们该如何对待它?它的类型为b
,但引用的类型为a
,因此周围的代码可能会使其行为类似于a
,而不是b
!
要消除歧义,我会引入virtual
关键字。如果对象是包含具有相同签名的方法的子类,则始终覆盖virtual
个函数。
干杯!
答案 3 :(得分:-1)
将a::print()
声明为虚拟,并使用指针/引用来调用print()
函数。执行blah[5] = b()
时,它会进行对象切片。使用object调用虚函数没有任何效果。