Вызов метода производного класса из указателя базового класса

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();