4

I try the following code, and get a compilation error.

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;
}

How to work around to make f(pB) call the f(A*&p) function?

Daniel Heilper
  • 1,182
  • 2
  • 17
  • 34
user1899020
  • 13,167
  • 21
  • 79
  • 154
  • My two cents, but it want get above the noise below. The reason you can't cast reference types like this is the same reason you can't cast pointer types like this. A** is a pointer to a pointer, B** is a pointer to a pointer. While you can cast B* to an A*, it doesn't mean you can cast the pointers to them. It is like trying to cast an `int32_t*` to a `uint32_t*`: just because you can cast an int32_t to a uint32_t (with no byte changes) their pointers loose that relationship. – IdeaHat May 23 '14 at 16:49

4 Answers4

6

A pointer variable passed to a non-const reference must match the same data type as the reference. The function is expecting a reference to an A* pointer so that is what you have to give it. If you have a B* pointer to start with, assign it to an A* variable first (since B derives from A):

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

But if the function modifies the pointer it is passed, it will modify pA not pB. If you need it to modify pB instead, you will have to re-think your design.

If you qualify the parameter as const, thereby guaranteeing that f won't modify it, then there is no problem:

void f(A* const & p) { /* Compiles fine */ }
Remy Lebeau
  • 555,201
  • 31
  • 458
  • 770
  • 3
    "The variable passed to a reference must match the same data type as the reference" that's not true in case of inheritance – lisyarus May 23 '14 at 15:50
  • It is true if the reference is not `const`, as in this example. If the reference were `const` then the compiler can implictly pass a derived class to a base class reference. – Remy Lebeau May 23 '14 at 15:52
  • 1
    it is not true even without const qualifier. Consider this: http://pastebin.com/6fWr7z6h – lisyarus May 23 '14 at 16:20
  • 1
    what is the point of passing a non-const reference? he probably intended to modify the pointer – Daniel Heilper May 23 '14 at 16:23
5

You can't do this, and here's why. Suppose it was allowed and f() looked like this:

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

Now you do this:

B* pB;
f(pB);

When f() returns, pB will be pointing to an A. Kaboom!

dlf
  • 9,045
  • 4
  • 32
  • 58
0

In your code the function f takes "a pointer to class A by reference". You cannot dynamically convert a "reference to a A-pointer" into a "reference to a B-pointer": while the B class is derived from the A class (and therefore a B-reference is dynamically converted into a A-reference) a B-pointer is still not a derived class of a A-pointer. Your attempt to mix pointers and references doesn't even make a lot of sense I think. You should simply modify your code into

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;
}
Emerald Weapon
  • 2,392
  • 18
  • 29
0

The previous answers explained very nicely why your code can't work. If you want to have a nice workaround to your problem, you can use template function of 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;
}
Daniel Heilper
  • 1,182
  • 2
  • 17
  • 34