Search code examples
c++inheritancepointersreferenceupcasting

Upcasting pointer reference


I have the following contrived example (coming from real code):

template <class T>
class Base {
public:
 Base(int a):x(a) {}
    Base(Base<T> * &other) { }
    virtual ~Base() {}
private:
 int x;
};

template <class T>
class Derived:public Base<T>{
public:
  Derived(int x):Base<T>(x) {}
  Derived(Derived<T>* &other): Base<T>(other) {}

};


int main() {
 Derived<int> *x=new Derived<int>(1);
 Derived<int> y(x);
}

When I try to compile this, I get:

1X.cc: In constructor ‘Derived<T>::Derived(Derived<T>*&) [with T = int]’:
1X.cc:27:   instantiated from here
1X.cc:20: error: invalid conversion from ‘Derived<int>*’ to ‘int’
1X.cc:20: error:   initializing argument 1 of ‘Base<T>::Base(int) [with T = int]’

1) Clearly gcc is being confused by the constructors. If I remove the reference from the constructors, then the code compiles. So my assumption is that something goes wrong with up-casting pointer references. Can someone tell me what is going on here?

2) A slightly unrelated question. If I were to do something horrendous like "delete other" in the constructor (bear with me), what happens when someone passes me a pointer to something on the stack ?

E.g. Derived<int> x(2);
     Derived<int> y(x);

where 

 Derived(Derived<T>*& other) { delete other;}

How can I make sure that pointer is legitimately pointing to something on the heap?


Solution

  • Base<T> is a base type of Derived<T>, but Base<T>* is not a base type of Derived<T>*. You can pass a derived pointer in place of a base pointer, but you can't pass a derived pointer reference in place of a base pointer reference.

    The reason is that, suppose you could, and suppose the constructor of Base were to write some value into the reference:

    Base(Base<T> * &other) {
        Base<T> *thing = new Base<T>(12);
        other = thing;
    }
    

    You've just written a pointer to something which is not a Derived<T>, into a pointer to Derived<T>. The compiler can't let this happen.