调用函数的childs版本而不是父母?

时间:2011-04-13 04:30:26

标签: c++ inheritance virtual override

好的,我有两节课。

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();

但是它叫父母。我该如何解决这个问题?

4 个答案:

答案 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调用虚函数没有任何效果。