Наследование и указатели на указатели: почему это не работает и как мне обойти это? - PullRequest
3 голосов
/ 27 июля 2010

Почему я получаю ошибку компиляции, когда вызываю функцию базового класса с указателем на указатель на унаследованный класс?

Пример:

class cFoo {};
class cBar : public cFoo {};
void func1(cFoo *) {}  // base class
void func2(cFoo **) {}  // base class

void main(void)
{   cBar bar, *pbar;   // inherited class

    func1(&bar);   // compiles OK
    func2(&pbar);  // fail
    func2(dynamic_cast<cFoo**>(&pbar));  // 'class cFoo ** ' : invalid target type for dynamic_cast
}

Как получитьвокруг этого?

Ответы [ 3 ]

6 голосов
/ 27 июля 2010

Рассмотрим следующее:

class cFoo {};
class cBar : public cFoo {};
void func1(cFoo *) {}
void func2(cFoo **p) { *p = new cFoo; }  // modify pointee

void main(void)
{   cBar bar, *pbar;   // inherited class

    func1(&bar);   // compiles OK

    func2(&pbar);
}

Если бы это сработало, вам бы удалось поместить объект cFoo в указатель cBar без ошибки компилятора, и система типов была бы подорвана.Динамическое приведение не помогло бы, так как это никак не могло предотвратить повреждение.

2 голосов
/ 27 июля 2010

Не работает, потому что dynamic_cast работает с указателями или ссылками на классы.И вы пытаетесь использовать его для указателей на указатели.

Простое исправление будет выглядеть примерно так:

func2(&dynamic_cast<cFoo*>(pbar));
0 голосов
/ 27 июля 2010

То, что вы пытаетесь сделать, ошибочно.

Типичный вариант использования (неконстантного) указателя на указатель в качестве аргумента функции - это то, что функция будет изменять аргумент для указания указателя на некоторый экземпляр.

Это функция, которая выбирает экземпляр. Пример фабричного метода.

Тип аргумента описывает тип, который функция гарантирует быть действительной.

Если ваша функция гарантировала, что экземпляр был cBar, тогда она должна принимать аргумент cBar **.

Поскольку он принимает cFoo **, он только гарантирует, что объект является действительным cFoo.

В текущей форме, если вы вызовете приведение, вы заставите любой тип cFoo быть представленным как cBar - даже если это не так.

...