3

I have an Abstract class, say Animal. From this class, I have many inheriting classes, such as Cat, Dog, Mouse. I have a method that I want to be able to take pointers to pointers of these objects. So void someMethod(Animal **anAnimal);

How is this accomplished? It seems I am not able to cast upwards like this. I am trying the following:

Dog *d = new Dog(x); //some parameter x.
Animal **animal = &d;
someMethod(animal);

//where someMethod has the method signature...
void someMethod(Animal **anAnimal);

What am I doing wrong, and how can I accomplish what I'm attempting?

vapo
  • 235
  • 2
  • 4
  • 9
  • 1
    Aside from the pointer question, why would you want double pointers? The only good application of double pointers that I know of, is when you want to modify where an incoming pointer points to. But in C++, that is better done with a reference: `void someMethod(Animal*& anAnimal)` now takes a reference to a pointer, and is able to modify the passed in pointer, without the double pointers needed. – Xeo Mar 27 '11 at 02:24
  • 1
    Why is this better than a double pointer?? Passing non-const references arguments is generally decouraged. Dereferencing the double pointer makes it straightforward that you are modifying some external pointer, while in your case it's not. And from a compiler point of view, both are generally identical regarding generated code. – galinette Sep 03 '13 at 06:32

3 Answers3

10

You need an Animal*:

Dog* d = new Dog(x);
Animal* a = d;
Animal** animal = &a;
someMethod(animal);

An Animal** can only point to an Animal*. It would be very bad if it could point to a Dog*. If it could, you could do something like this:

Dog* d = new Dog(x);
Animal** animal = &d;
*animal = new Hippopotamus();

Now d points to a Hippopotamus, which is very wrong indeed.

James McNellis
  • 348,265
  • 75
  • 913
  • 977
0

You need to introduce a temporary of type Animal*:

Dog *d = new Dog(x); //some parameter x.
Animal *a = d;
Animal **animal = &a;
someMethod(animal);

The reason for this is that &d is Dog**, which cannot be converted to Animal** even if Dog* can be converted to Animal*.

Normally you 'd fix this inline using something like this (warning -- does not compile!):

Dog *d = new Dog(x); //some parameter x.
Animal **animal = &(static_cast<Animal*>(d));
someMethod(animal);

However, this is not possible because the return value of static_cast is a temporary (technically, its a rvalue) so you cannot get its address. Therefore, you need the extra Animal* local to make this work.

Jon
  • 428,835
  • 81
  • 738
  • 806
0

Going to have to do a cast.

Animal **animal = (Animal **)&d;
Suroot
  • 4,315
  • 1
  • 22
  • 28
  • Not sure why I was dinged; can someone provide some input as to why this is a bad implementation? It compiles and works properly in GCC (g++). – Suroot Mar 27 '11 at 02:42
  • `class Animal {} ; class Graphic {}; class Dog : public Graphic, public Animal {}; Dog *pDog = 0; Animal *pAnimal = pDog; /* This compiles, and the code is correct. pAnimal points to the Animal part of pDog. */ Animal **ppAnimal = (Animal **)&pDog; /* This compiles, but the code is broken. *ppAnimal may point to the Graphic part of pDog, depending on the compiler implementation. */` – Thomas L Holaday Mar 27 '11 at 05:05