4

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

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) 函数?

4

4 回答 4

6

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

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

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

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

void f(A* const & p) { /* Compiles fine */ }
于 2014-05-23T15:48:31.287 回答
5

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

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

现在你这样做:

B* pB;
f(pB);

f()返回时,将pB指向一个A. 轰隆隆!

于 2014-05-23T15:52:23.260 回答
0

在您的代码中,函数 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;
}
于 2014-05-23T15:59:30.933 回答
0

先前的答案很好地解释了为什么您的代码无法工作。如果你想对你的问题有一个很好的解决方法,你可以使用 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;
}
于 2014-05-23T16:31:10.813 回答