如何实现多态向下类型的自动转换?

sfxyz7 2015-03-22 06:24:24
#include <iostream>
#include <typeinfo>
#include <string>
using namespace std;
class animal
{
public:
virtual void breathe(){ cout << "animal bubble" << endl; }
virtual animal* getThis(){ return this; }
};

class fish : public animal
{
public:
void breathe(){ cout << "fish bubble" << endl; }
void eat(){ cout << "fish eat" << endl; }
animal* getThis(){ return this; }
};
int main()
{
animal *pa;
fish f;
pa = &f;
cout << typeid(pa->getThis()).name() << endl;
cout << typeid(f).name() << endl;

// pa->getThis()->eat();
return 0;
}
//----------------------------------------------------------------------------------------------------------
为什么 typeid(pa->getThis()).name()和 typeid(f).name()返回的类型不一样?
getThis函数返回当前对象的指针,应该是fish*,为什么注释掉那行语句是错误的?
不强制转换类型,怎么才可以让注释掉的那行代码正常运行?
...全文
242 14 打赏 收藏 转发到动态 举报
写回复
用AI写文章
14 条回复
切换为时间正序
请发表友善的回复…
发表回复
jiht594 2015-03-29
  • 打赏
  • 举报
回复
引用 13 楼 sfxyz7 的回复:
[quote=引用 11 楼 jianwen0529 的回复:] [quote=引用 9 楼 jianwen0529 的回复:] 函数和变量的可见范围是基于静态类型,而不是动态类型 就例如你的 animal *pa; fish f; pa = &f; pa的静态类型是animal ,只能可见breathe, animal函数,对你派生类的eat函数是不可见的 你不能用pa去调用它(即使pa的动态类型是fish)
更加清晰的解释:你既然是动态类型,就是运行时才知道的类型。你pa->getThis()->eat()本来就是静态编译的,那么编译器如何知道你pa可以调用eat[/quote] pa->getThis()->eat()本来就是静态编译的,这句话怎么理解?如果是静态编译的应该是可以通过编译的吧,但是很明显不能通过编译。设计确实有些问题,不过eat行为只是测试用的^_^。[/quote] 他说静态编译, 是指"调用哪个函数编译期就决定了, 而不是运行期决定的", 但是静态编译是找不到eat函数的, 失败是对的.
sfxyz7 2015-03-29
  • 打赏
  • 举报
回复
引用 11 楼 jianwen0529 的回复:
[quote=引用 9 楼 jianwen0529 的回复:] 函数和变量的可见范围是基于静态类型,而不是动态类型 就例如你的 animal *pa; fish f; pa = &f; pa的静态类型是animal ,只能可见breathe, animal函数,对你派生类的eat函数是不可见的 你不能用pa去调用它(即使pa的动态类型是fish)
更加清晰的解释:你既然是动态类型,就是运行时才知道的类型。你pa->getThis()->eat()本来就是静态编译的,那么编译器如何知道你pa可以调用eat[/quote] pa->getThis()->eat()本来就是静态编译的,这句话怎么理解?如果是静态编译的应该是可以通过编译的吧,但是很明显不能通过编译。设计确实有些问题,不过eat行为只是测试用的^_^。
liusuzi2011 2015-03-27
  • 打赏
  • 举报
回复
楼上正解,想搞多态,肯定是有虚函数,即接口。如果eat父类没有,编译时肯定是不过的
幻夢之葉 2015-03-27
  • 打赏
  • 举报
回复
引用 9 楼 jianwen0529 的回复:
函数和变量的可见范围是基于静态类型,而不是动态类型 就例如你的 animal *pa; fish f; pa = &f; pa的静态类型是animal ,只能可见breathe, animal函数,对你派生类的eat函数是不可见的 你不能用pa去调用它(即使pa的动态类型是fish)
更加清晰的解释:你既然是动态类型,就是运行时才知道的类型。你pa->getThis()->eat()本来就是静态编译的,那么编译器如何知道你pa可以调用eat
幻夢之葉 2015-03-27
  • 打赏
  • 举报
回复
况且你的设计也是有些问题的! eat不是所有动物都具有的动作吗,完全可以放在基类里面 派生是说在基类的基础上增加或修正某些属性和动作 就比如你eat fish吃的是什么食料(水草),需要吃多少量,什么时候进食等等 特点属性有鱼鳍等 再然后你增加诸如鸡,吃米饭,虫子 特点属性可以有两肢,鸡冠
幻夢之葉 2015-03-27
  • 打赏
  • 举报
回复
函数和变量的可见范围是基于静态类型,而不是动态类型 就例如你的 animal *pa; fish f; pa = &f; pa的静态类型是animal ,只能可见breathe, animal函数,对你派生类的eat函数是不可见的 你不能用pa去调用它(即使pa的动态类型是fish)
xionggch 2015-03-27
  • 打赏
  • 举报
回复
animal *pa; //这已经定pa为animal类的指针了,eat();是派生类中的函数 fish f; pa = &f;
南城边 2015-03-26
  • 打赏
  • 举报
回复
1、为什么 typeid(pa->getThis()).name()和 typeid(f).name()返回的类型不一样? typeid(pa->getThis()).name() 取得的是 animal* 的标识符 使用typeid(*pa->getThis()).name() 取得animal 的标识符,与typeid(f).name()返回的类型一致。 2、getThis函数返回当前对象的指针,应该是fish*。 getThis函数返回的是animal*,返回值的类型取决于函数声明,与多态无关。 当前对象的this指针的确是fish*,但是return this时,fish*会被自动转换为animal*,因为派生类指针可以隐式转换为基类指针。 使用animal*来调用fish中定义的eat自然是不允许的。 只能使用强制类型转换。或者只能重新设计,将eat定义为animal的虚函数。
sfxyz7 2015-03-25
  • 打赏
  • 举报
回复
引用 3 楼 worldy 的回复:
那需要使用派生类的指针作为基准,不能使用原始基类
意思就是说除了强制转换的方法,其他方法都是行不通的?
sfxyz7 2015-03-25
  • 打赏
  • 举报
回复
引用 4 楼 hanyue03 的回复:
多态要用指针 或者引用,直接对象是不行的
就是使用的指针啊。
hanyue03 2015-03-22
  • 打赏
  • 举报
回复
多态要用指针 或者引用,直接对象是不行的
worldy 2015-03-22
  • 打赏
  • 举报
回复
那需要使用派生类的指针作为基准,不能使用原始基类
sfxyz7 2015-03-22
  • 打赏
  • 举报
回复
引用 1 楼 worldy 的回复:
既然使用了虚拟函数,还GetThis干吗? 把eat弄做动物类的虚拟函数,pa就可以直接eat(),不同的动物就会使用自己的eat方法 pa->eat(); 即可
加入派生类又有了不同于基类的虚函数,这个时候有什么办法不使用强制类型转换直接用基类指针获取派生类的自己的不属于基类的虚函数?
worldy 2015-03-22
  • 打赏
  • 举报
回复
既然使用了虚拟函数,还GetThis干吗? 把eat弄做动物类的虚拟函数,pa就可以直接eat(),不同的动物就会使用自己的eat方法 pa->eat(); 即可

64,646

社区成员

发帖
与我相关
我的任务
社区描述
C++ 语言相关问题讨论,技术干货分享,前沿动态等
c++ 技术论坛(原bbs)
社区管理员
  • C++ 语言社区
  • encoderlee
  • paschen
加入社区
  • 近7日
  • 近30日
  • 至今
社区公告
  1. 请不要发布与C++技术无关的贴子
  2. 请不要发布与技术无关的招聘、广告的帖子
  3. 请尽可能的描述清楚你的问题,如果涉及到代码请尽可能的格式化一下

试试用AI创作助手写篇文章吧