2011-04-13 23 views
8

好吧,我有两堂课。调用函数的childs版本而不是父母?

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

但它调用父项。我该如何解决?

回答

11

这可以是固定的通过声明功能虚拟,一拉:

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

声明a::print()作为虚拟和使用指针/参考调用print()功能。当你做blah[5] = b()时,它会进行对象切片。使用对象调用虚函数没有任何效果。

0

它确实是因为你告诉编译器,你的情况是a型。它在一组a对象中,对吗?所以它是a

当然,尽管有父类型的引用,但您仍希望b中的方法覆盖a中的方法。您可以在父类的函数声明中使用关键字virutal来获得该行为。

virtual void print(){cout << "hello"}; 

它为什么会这样工作?

因为当你将对象转换到父类时,引入了一个模糊性。当这个对象的print()被调用时,我们应该如何处理它?它的类型为b,但是引用的类型为a,所以该代码可能预期它的行为类似于a而不是b

为了消除歧义,引入了virtual关键字。如果对象是包含具有相同签名的方法的子类,则函数总是被覆盖。

干杯!

2

您正在寻找的是运行时多态性,这意味着让对象采用“多种形式”(即a或b),并随着程序运行相应地采取行动。在C++中,这样做通过使功能virtual在基类a

virtual void print() {cout << "hello"}; 

然后,需要存储由指针或引用的元素,以及 - 如在一般的派生类可以引入新的数据成员并且需要更多的存储 - 这是正常的与new在堆上创建的对象:

a* blah[10]; 
blah[5] = new b(); 

然后,您可以拨打:

blah[5]->print(); 

它会调用print()b实现。

您应该稍后delete blah[5](以及您指向的任何其他内存由new返回)。

在实践中,最好使用一个容器,当容器本身被破坏时,可以删除它所包含的对象,无论是由于留下作用域还是被删除。 std::vector<>就是这样一个容器。您还可以使用智能指针来自动删除ab对象。如果在执行delete语句之前抛出异常,并且希望程序保持运行而不泄漏内存,这有助于使代码正确。 boost库是从中获得智能指针实现的最简单/最好的地方。总之:

#include <vector> 
#include <boost/shared_ptr.hpp> 

std::vector<boost::shared_pointer<a> > blah(10); 

blah[5] = new b(); 

(这是比较正常的使用向量与push_back(),因为它通过调用vector::size()自动增长,以适应在所有已添加的元素,新的总可用的矢量。)

相关问题