2013-11-28 1 views
0

У меня проблема с наследованием в C++. Приложенный код производит вывод «1,1», но я думал, что методы действий из классов b и c заменяют метод действия из класса a. Поэтому я ожидал выход «2,3,». Что мне нужно изменить, чтобы получить результат «2,3,»?Наследование C++, функция не заменена в дочернем классе

#include <iostream> 

//Class a 

class a 
{ 
public: 
    a(); 
    int action(); 
}; 

a::a() 
{ 
} 

int a::action() 
{ 
    return 1; 
} 

//Class b 

class b : public a 
{ 
public: 
    b(); 
    int action(); 
}; 

b::b() 
{ 
} 

int b::action() 
{ 
    return 2; 
} 

//Class c 

class c : public a 
{ 
public: 
    c(); 
    int action(); 
}; 

c::c() 
{ 
} 

int c::action() 
{ 
    return 3; 
} 

//Main Programm 

int main() 
{ 
    a arr[2]; 
    arr[0] = b(); 
    arr[1] = c(); 

    for(int i = 0; i<2; i++) 
    { 
     std::cout << arr[0].action() << ","; 
    } 

    return 0; 
} 
+2

Вы должны объявить метод как виртуальный, и он должен быть вызван с помощью указателя. – IronMensan

+0

В частности, строка 'arr [0] = b();' приводит к тому, что объект типа 'b' создается по умолчанию, а затем набрасывается на тип' a', поэтому его можно сохранить в массиве. Приведение к 'a' означает, что результат больше не является' b', поэтому 'b :: action' не применяется. – Steve314

+1

@ Steve314 - нет никакого кода в коде. Значение ** преобразуется ** в тип 'a'. –

ответ

1

вы можете использовать виртуальную функцию, чтобы получить выход «2,3»:
первых, вы должны change void action(); к virtual void action(); в классе а;
Во-вторых, вы должны использовать указатель для реализации полиморфизма;
третьих, вы должны изменить arr[0] на arr[i];

Вот мой код:

#include <iostream> 

//Class a 

class a 
{ 
public: 
    a(); 
    virtual int action(); 
}; 

a::a() 
{ 
} 

int a::action() 
{ 
    return 1; 
} 

//Class b 

class b : public a 
{ 
public: 
    b(); 
    int action(); 
}; 

b::b() 
{ 
} 

int b::action() 
{ 
    return 2; 
} 

//Class c 

class c : public a 
{ 
public: 
    c(); 
    int action(); 
}; 

c::c() 
{ 
} 

int c::action() 
{ 
    return 3; 
} 

int main(int argc, char *argv[]) 
{ 
    a *(arr[2]); 
    arr[0] = new b(); 
    arr[1] = new c(); 

    for(int i = 0; i<2; i++) 
    { 
     std::cout << arr[i]->action() << ","; 
    } 

    return 0; 
} 

Вот мой результат:
enter image description here

2

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

Вы можете использовать нотацию foo() override, чтобы получить проверку времени компиляции относительно того, действительно ли вы что-то переопределяете.

Вам придется получить доступ к производному типу через указатель на базовый тип, иначе вы будете нарезать и делать другие неприятные вещи. Также иногда также полезно сделать ваш деструктор виртуальным.

class Base { }; 
class Derived : public Base { }; 

some_container<Base*> baseOrDerived; 

Затем вы можете выделить как базовый, так и производный объекты в этот контейнер. Например, с new, хотя вы, вероятно, захотите использовать std::shared_ptr<Base> or std::unique_ptr<Base> вместо Base*.

+0

Если я делаю метод действия виртуальным в базовом классе, появляется ошибка, что я не могу создать массив абстрактного класса. Но мне нужны экземпляры разных дочерних классов, хранящихся в массиве. У вас есть идея, как это сделать? Может быть, вы можете исправить мой код, потому что у меня почти нет опыта с наследованием. – Felix

+2

@Felix: Ваш массив должен быть массивом (умных) указателей. –

+0

@VaughnCato Мои опыты с указателями, к сожалению, тоже очень мало. Так что, пожалуйста, напишите мне пример того, как вы это реализуете. – Felix

Смежные вопросы