读书人

大概关于虚函数的有关问题

发布时间: 2012-03-21 13:33:14 作者: rapoo

大概关于虚函数的问题

在第33行, ptr -> cloen(), clone()是虚函数, 所以会调用第21行Dog类哪的clone()函数。

我的问题是: 在第21行里, clone()函数内的代码 this 应该是一个 Dog 类的指针, 而ptr是一个 Mammal 类指针, 为什么不会产生错误呢?

谢谢


1 #include <iostream>
2
3 using namespace std;
4
5 class Mammal
6 {
7 public:
8 Mammal(){};
9 virtual ~Mammal() {};
10 Mammal(const Mammal&) {};
11 virtual Mammal* clone() {return new Mammal(*this);}
12 };
13
14
15 class Dog : public Mammal
16 {
17 public:
18 Dog() {};
19 virtual ~Dog() {};
20 Dog(const Dog&);
21 virtual Mammal* clone() {return new Dog(*this);}
22 };
23
24
25 Dog::Dog(const Dog& rhs):
26 Mammal(rhs)
27 {}
28
29
30 int main(void)
31 {
32 Mammal *ptr = new Dog;
33 Mammal *p = ptr -> clone();
34 return 0;
35 }



[解决办法]
派生类的指针可以直接赋给基类的指针,反之则有强制类型转换
[解决办法]
ptr是一个 Mammal 类指针,就如同ls说的“派生类的指针可以直接赋给基类的指针”,这一Mammal 类指针指向一个dog类对象,所白了就是一个dog实例的首地址。
在第21行里, clone()函数内的代码 this 应该是一个 Dog 类的指针-----》由于clone是虚函数,虽然ptr是指向dog类对象的mamal指针,调用时,要用dog类中的clone函数,而你认为此时this指向一个mamal对象了,其实不是,指向的是dog对象
这个就是虚函数的多态性的一个例子
[解决办法]
而ptr是一个 Mammal 类指针, 为什么不会产生错误呢

派生类类型指针 赋值给 基类类型指针是可以的,
因为 基类指针 所允许的调用,派生类类型指针都可以完成。

而反过来是可能会发生错误的,
所以不允许 用派生类类型指针 赋值为 基类类型指针。
[解决办法]
基类类型 *pBase = new 派生类类型; //OK
派生类类型 *pDrived = new 基类类型; //Error !

由于派生,
pDrived 允许的调用,比如某个方法,
可能是 基类 中不支持的,
那么 pDrived-> 该方法 就会发生错误。

而pBase 允许的调用,
new 派生类类型 返回的对象实例必然是可用的。

如果还不理解,
记住这个规则,以后再慢慢理解去吧。
[解决办法]
建议楼主看看C++的虚函数机制

这个clone()方法是设计模式里的 原型模式,能在不知道具体子类的情况下实现对子类的克隆。



通过基类的指针调用虚函数clone(),而虚函数机制会关联到实际子类clone()函数,再由实际的子类完成自我复制。

比如有这样一个函数:Mammal* CreateMamal(Mammal* pM)能根据传进来的pM指针复制生成一个类Mammal

Mammal* CreateMamal(Mammal* pM)
{
return pM-> clone(); //调用clone()方法实现克隆
}
在这个函数里,我们不知道任何pM所指向的实际的类信息,但是通过虚机制,我们却能准确地复制一份pM所指向类的拷贝

读书人网 >C++

热点推荐