2013-06-25 4 views
2

У меня есть следующий фрагмент кода (#include с и using namespace std опущена):C++: Виртуальные методы

class A { 
    public: 
     void call(){callme();} 
    private: 
     virtual void callme() {cout << "I'm A" << endl;} 
}; 

class B : public A { 
    private: 
     virtual void callme() {cout << "I'm B" << endl;} 
}; 

class C : public B { 
    public: 
     virtual void callme(){ cout << "I'm C" << endl;} 
}; 

int main(){ 
    vector<A> stuff = { 
     A(), B(), C(), 
    }; 
    stuff[0].call(); // output: I'm A 
    stuff[1].call(); // output: I'm A 
    stuff[2].call(); // output: I'm A 
    return 0; 
} 

Как указано в комментариях, выход выше программы является:

I'm A 
I'm A 
I'm A 

Однако я хотел бы, чтобы C++ автоматически распознавал тип, с которым был создан соответствующий элемент. То есть Я хотел бы, чтобы результаты C++

I'm A 
I'm B 
I'm C 

(То есть, компилятор должен выбрать правильный подкласс для меня.)

Возможно ли это в данном случае (т.е. если все элементы выходят из vector) ?

+5

См: [? В чем проблема нарезка] (http://stackoverflow.com/questions/274626/what-is-the-slicing-problem -in-c) – jrok

ответ

2

Член функция виртуальность работает только при вызове их из указателя на реальный объект, а не от самого объекта, так как в вашем примере объектах были автоматически статический upcasted класса А. Изменить код:

std::vector<std::unique_ptr<A>> stuff = { 
    std::unique_ptr<A>(new A()), 
    std::unique_ptr<A>(new B()), 
    std::unique_ptr<A>(new C()), 
}; 
stuff[0]->call(); 
stuff[1]->call(); 
stuff[2]->call(); 
+1

's/A */std :: unique_ptr /' ... – Griwes

+0

OP не обязательно знает о умных указателях, особенно если он задает такой базовый вопрос –

+4

Тогда самое подходящее время научить его о них , ПРЕЖДЕ ЧЕМ УЧИТЬСЯ, владея сырыми указателями, FFS. – Griwes

1

Для полиморфизма C++ вы должны использовать либо указатель, либо ссылку. Вы могли бы сделать, как этот

int main(){ 
     vector<A*> stuff; 
     stuff.push_back(new A); 
     stuff.push_back(new B); 
     stuff.push_back(new C); 
     stuff[0]->call(); // output: I'm A 
     stuff[1]->call(); // output: I'm A 
     stuff[2]->call(); // output: I'm A 
     while (!stuff.empty()){ 
       delete stuff.back(); 
       stuff.pop_back(); 
     } 
     return 0; 
} 

Артикул: http://www.cplusplus.com/doc/tutorial/polymorphism/

+1

Внимание! Посмотрите на комментарии к моему ответу. У вас также есть небезопасный код –