免费注册 查看新帖 |

Chinaunix

  平台 论坛 博客 文库
最近访问板块 发新帖
查看: 4381 | 回复: 5
打印 上一主题 下一主题

函数参数为基类指针的引用,为何不能传子类的指针给它? [复制链接]

论坛徽章:
0
跳转到指定楼层
1 [收藏(0)] [报告]
发表于 2012-04-01 13:53 |只看该作者 |倒序浏览
代码:
  1. #include <list>

  2. class ICommand{};
  3. class CSession : public ICommand{};

  4. void Test(ICommand * & pCommand){}

  5. int main(int argc, char *argv[])
  6. {
  7.        std::list<ICommand*> commands;
  8.        std::list<CSession*> sessions;

  9.        Test(*commands.begin());
  10.        Test(*sessions.begin());
  11.        
  12.        return 0;
  13. }
复制代码
Test(*sessions.begin())一行:error C2664: 'Test' : cannot convert parameter 1 from 'CSession *' to 'ICommand *&'

论坛徽章:
14
巨蟹座
日期:2013-11-19 14:09:4615-16赛季CBA联赛之青岛
日期:2016-07-05 12:36:0515-16赛季CBA联赛之广东
日期:2016-06-29 11:45:542015亚冠之全北现代
日期:2015-07-22 08:09:472015年辞旧岁徽章
日期:2015-03-03 16:54:15巨蟹座
日期:2014-12-29 08:22:29射手座
日期:2014-12-05 08:20:39狮子座
日期:2014-11-05 12:33:52寅虎
日期:2014-08-13 09:01:31巳蛇
日期:2014-06-16 16:29:52技术图书徽章
日期:2014-04-15 08:44:01天蝎座
日期:2014-03-11 13:06:45
2 [报告]
发表于 2012-04-01 14:08 |只看该作者
很显然的
如果这是允许的……,还是用代码来说吧
  1. struct base {};
  2. struct foo : base {};

  3. int main()
  4. {
  5.         foo* p = new foo;

  6.         base*& pb = p;

  7.         pb = new base;

  8.         return 0;
  9. }
复制代码
如果此语法能通过的话,此后(就是pb = p以后),p的静态类型为foo,但动态类型将变为base
所以你这个问题等同于为什么不能 foo* p = new base 一样

论坛徽章:
5
狮子座
日期:2013-08-20 10:12:24午马
日期:2013-11-23 18:04:102015年辞旧岁徽章
日期:2015-03-03 16:54:152015亚冠之德黑兰石油
日期:2015-06-29 18:11:1115-16赛季CBA联赛之新疆
日期:2024-02-21 10:00:53
3 [报告]
发表于 2012-04-01 14:13 |只看该作者
回复 2# bruceteen


    动态类型是根本不会变的啦。

根本原因是,B是D的基类,然而B*不是D*的基类,你可以试试:

foo *p = new foo();
base **pb = &p;

看看是啥结果。

论坛徽章:
0
4 [报告]
发表于 2012-04-01 15:11 |只看该作者
本帖最后由 csoapy 于 2012-04-01 15:24 编辑

谢谢楼上两位,总算明白了原因。
就是D is a kind of B, but a pointer to D is not a kind of a pointer  to B.
也就是,指针就是指针,无继承关系。不能说一种指针是另一种指针,即使它们指向的类是继承关系。

Test()的原意是,操作ICommand * & pCommand,然后再把pCommand值空。所以要传引用,或者二级指针,但是都通不过。一时还没想出来该怎么办,只想在Test()中delete 该指针,然后值空。作了如下修改,但仍旧通不过。还是cannot convert parameter 1 from 'ICommand *' to 'ICommand *&',也许是我还是没明白?

  1. #include <list>

  2. class ICommand{};
  3. class CSession : public ICommand{};

  4. void Test(ICommand * & pCommand){delete pCommand; pCommand = NULL;}

  5. int main(int argc, char *argv[])
  6. {
  7.         ICommand * pCommand = new ICommand();
  8.         CSession * pSession = new CSession();

  9.         std::list<ICommand*> commands;        commands.push_back(pCommand);
  10.         std::list<CSession*> sessions;        sessions.push_back(pSession);

  11.         Test(*commands.begin());

  12.         ICommand *p = dynamic_cast<ICommand*>(*sessions.begin());
  13.         Test(p);

  14.         sessions.push_back(new CSession());

  15.         Test(dynamic_cast<ICommand*>(*sessions.begin())); // cannot convert parameter 1 from 'ICommand *' to 'ICommand *&'

  16.         return 0;
  17. }
复制代码

论坛徽章:
0
5 [报告]
发表于 2012-04-01 19:23 |只看该作者
唉,在编译时刻要保证引用必须指向一个对象,Test(dynamic_cast<ICommand*>(*sessions.begin())); 要求使用引用,但sessions.begin()返回的是临时的、运行时的,编译器不知道该把引用指向哪,所以报错

论坛徽章:
0
6 [报告]
发表于 2012-04-01 19:58 |只看该作者
本帖最后由 x5miao 于 2012-04-01 19:58 编辑

回复 5# csoapy


    这就如同使用变量可以绑定该变量的类型的引用,但却不允许引用的引用来绑定引用是一个道理。
您需要登录后才可以回帖 登录 | 注册

本版积分规则 发表回复

  

北京盛拓优讯信息技术有限公司. 版权所有 京ICP备16024965号-6 北京市公安局海淀分局网监中心备案编号:11010802020122 niuxiaotong@pcpop.com 17352615567
未成年举报专区
中国互联网协会会员  联系我们:huangweiwei@itpub.net
感谢所有关心和支持过ChinaUnix的朋友们 转载本站内容请注明原作者名及出处

清除 Cookies - ChinaUnix - Archiver - WAP - TOP