Вызов метода производного класса из указателя базового класса
0 slier [2014-01-24 17:49:00]
//Parent.h
class Parent
{
public:
virtual void foo() = 0;
};
//Child.h
class Child : public Parent
{
public:
virtual void foo(){cout << "inside function foo()" << endl;}
virtual void bar(){cout << "inside function bar()" << endl;};
};
int main( int argc, char** argv ){
Parent* pa = new Child;
pa->foo();
pa->bar(); //Error, class Parent have no member bar
return 0;
}
Как избежать этой ошибки, кроме добавления этих функций в класс Parent
c++
4 ответа
2 Решение Eric Fortin [2014-01-24 17:52:00]
Вы можете объявить свой указатель как тип Child. Вы все равно сможете передать его функции, ожидая указателя родителя.
Другое решение включает использование dynamic_cast<Child>(pa)
хотя это часто рассматривается как плохой дизайн, который нуждается в этом, потому что он побеждает в том, что должен выполнять полиморфизм.
1 John Dibling [2014-01-24 18:12:00]
Вы избегаете этой ошибки, проявляя большую осторожность в своем классе, в первую очередь.
Да, вы можете использовать dynamic_cast
или static_cast
для приведения указателя Base
к Derived
указателю, если типы связаны, как они есть здесь. Но подумай об этом.
В: Почему вы используете полиморфизм? A: Чтобы обеспечить различное поведение для аналогичных операций, где поведение выбирается во время выполнения.
Полиморфизм используется для абстрагирования выполнения операции от предоставления этой операции. У всей Shape
например, есть несколько сторон. Сколько сторон зависит от фактической формы, но мы не должны знать, какой Shape
то есть для того, чтобы спросить его, сколько сторон у него есть. Мы должны просто спросить об этом.
В: Почему вам обычно нужно использовать dynamic_cast
?
A: Поскольку базовый указатель не предоставляет необходимые вам средства.
Если мы не должны заботиться, какая Shape
некоторого объект в целях выполнения операции нам нужно на ней, то почему бы Shape
интерфейс никогда не предоставляет любые объекты нам нужны?
Это происходит, когда мы ошиблись при создании чего-то. Либо Shape
не хватало или не было подходящих видов объектов, или какой-то конкретный подкласс Shape
пытается сделать больше, чем нужно.
Это то, что вы здесь сделали. Если для Parent
не имеет смысла использовать (public
) bar()
метод, то для Child
не имеет смысла иметь его. Если для Child
имеет смысл использовать метод bar
, то Child
самом деле не является Parent
, не так ли?
Может быть, bar
должен быть методом в каком-то другом классе.
0 niloydebnath [2014-01-24 18:54:00]
Сначала нам нужно знать, почему компилятор жалуется! Вы никогда не узнаете причину, если кто-нибудь скажет вам об этом. Сначала поймите причину.
Вы получаете ошибку во время компиляции. vTable
и vPtr
не появляются во время early binding
. Он появляется в картине в late binding
. Базовый класс не имеет метода бара, поэтому компилятор жалуется на то, что метод, вызванный базовым классом, неизвестен. Поэтому вам нужно привести его к указателю на производный класс, чтобы получить early binding
. Надеюсь, что я правильно понимаю проблему. Поправьте меня, если я ошибаюсь.
0 Wojtek Surowka [2014-01-24 17:52:00]
Вы можете использовать static или dynamic_cast. Пример с dynamic_cast:
if (Child* child = dynamic_cast<Child*>(pa))
child->bar();