Chinaunix

标题: 函数参数为基类指针的引用,为何不能传子类的指针给它? [打印本页]

作者: csoapy    时间: 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 *&'

作者: bruceteen    时间: 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 一样
作者: starwing83    时间: 2012-04-01 14:13
回复 2# bruceteen


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

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

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

看看是啥结果。
作者: csoapy    时间: 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. }
复制代码

作者: csoapy    时间: 2012-04-01 19:23
唉,在编译时刻要保证引用必须指向一个对象,Test(dynamic_cast<ICommand*>(*sessions.begin())); 要求使用引用,但sessions.begin()返回的是临时的、运行时的,编译器不知道该把引用指向哪,所以报错
作者: x5miao    时间: 2012-04-01 19:58
本帖最后由 x5miao 于 2012-04-01 19:58 编辑

回复 5# csoapy


    这就如同使用变量可以绑定该变量的类型的引用,但却不允许引用的引用来绑定引用是一个道理。




欢迎光临 Chinaunix (http://bbs.chinaunix.net/) Powered by Discuz! X3.2