【问题标题】:cannot convert from 'DerivedClass *' to 'BaseClass *&'无法从 'DerivedClass *' 转换为 'BaseClass *&'
【发布时间】:2014-07-13 01:19:10
【问题描述】:

我尝试下面的代码,并得到一个编译错误。

class A {};
class B : public A {};

void f(A*& p) {}

int
main()
{
    B* pB;
    f(pB); // cannot convert argument 1 from 'B *' to 'A *&'

    return 0;
}

如何让 f(pB) 调用 f(A*&p) 函数?

【问题讨论】:

  • 我的两分钱,但它想要超越下面的噪音。不能像这样转换引用类型的原因与不能像这样转换指针类型的原因是一样的。 A** 是指向指针的指针,B** 是指向指针的指针。虽然您可以将 B* 转换为 A*,但这并不意味着您可以将指针转换为它们。这就像试图将 int32_t* 转换为 uint32_t*:仅仅因为您可以将 int32_t 转换为 uint32_t(没有字节更改),它们的指针就会失去这种关系。

标签: c++ reference polymorphism pass-by-reference upcasting


【解决方案1】:

传递给非const 引用的指针变量必须与引用匹配相同的数据类型。该函数期望引用一个A* 指针,所以这就是你必须给它的。如果你有一个 B* 指针作为开头,首先将它分配给一个 A* 变量(因为 B 派生自 A):

B* pB = ...;
A* pA = pB;
f(pA);

但是如果函数修改了它传递的指针,它会修改pA而不是pB。如果您需要它来修改pB,您将不得不重新考虑您的设计。

如果你将参数限定为const,从而保证f不会修改它,那么就没有问题:

void f(A* const & p) { /* Compiles fine */ }

【讨论】:

  • “传递给引用的变量必须与引用匹配相同的数据类型”在继承的情况下不正确
  • 如果引用不是const,则为真,如本例所示。如果引用是const,那么编译器可以将派生类隐式传递给基类引用。
  • 即使没有 const 限定符也不正确。考虑一下:pastebin.com/6fWr7z6h
  • 传递非常量引用的意义何在?他可能打算修改指针
【解决方案2】:

你不能这样做,这就是原因。假设它被允许并且f() 看起来像这样:

void f(A*& p) { p = new A(); }

现在你这样做:

B* pB;
f(pB);

f() 返回时,pB 将指向A。轰隆隆!

【讨论】:

    【解决方案3】:

    在您的代码中,函数 f 采用“通过引用指向 A 类的指针”。 您不能将“对 A 指针的引用”动态转换为“对 B 指针的引用”:而 B 类派生自 A 类(因此 B 引用动态转换为 A 引用) B 指针仍然不是 A 指针的派生类。我认为您尝试混合指针和引用甚至没有多大意义。 您只需将代码修改为

    class A {};
    class B : public A {};
    
    void f( A & p) {}
    
    int
    main()
    {
        B pB;
        f(pB); // you are now passing a B object by reference
    
        return 0;
    }
    

    【讨论】:

      【解决方案4】:

      前面的答案很好地解释了为什么您的代码无法运行。 如果你想对你的问题有一个很好的解决方法,你可以使用 foo 的模板函数:

      class A {
      public:
          A() {}
          A(A*) {}
          virtual ~A() {}
      };
      class B : public A {
      public:
          B () {}
          B(B*) {}
          virtual ~B() {}
      };
      
      template <class A, class B> 
      B* foo(A* p) {
          //do something related to p - delete, or something
          B* p_new = new B(dynamic_cast <B*> (p));
          return p_new;
      }
      int
      main()
      {
          B* pB = new B;      
          pB = foo <A,B> (pB);
          return 0;
      }
      

      【讨论】:

        猜你喜欢
        • 2013-06-02
        • 2010-12-21
        • 1970-01-01
        相关资源
        最近更新 更多