2013-03-12 4 views
2

Первый класс:Виртуальная функция не работает

class SistemPornire{ 
protected: 
    Motor &_motor; 
    Electromotor &_electromotor; 

public: 
    SistemPornire(Motor&,Electromotor&); 
    virtual void pornire_motor(); 
    void opreste_motor(); 
}; 

Реализация виртуальной функции:

SistemPornire::SistemPornire(Motor &motor, Electromotor &electromotor) 
    :_motor(motor), _electromotor(electromotor) 
{ 
} 

void SistemPornire::pornire_motor() 
{ 
    std::cout << "Sistemul de pornire a trimis comanda porneste_motor electromotorului." << std::endl; 
    this->_electromotor.start(_motor); 
} 

Второй класс:

class SistemPornireCuPreincalzire:public SistemPornire { 
public: 
    SistemPornireCuPreincalzire(Motor&,Electromotor&); 
    void pornire_motor(); 
}; 

Его реализация:

SistemPornireCuPreincalzire::SistemPornireCuPreincalzire(Motor&motor, Electromotor&electromotor) 
    : SistemPornire(motor, electromotor) 
{ 

} 

void SistemPornireCuPreincalzire::pornire_motor() 
{ 
    std::cout << "A inceput preincalzirea" <<std::endl<< "Preincalzirea incheiata" << std::endl; 

    std::cout << "Sistemul de pornire a trimis comanda porneste_motor electromotorului." << std::endl; 
    this->_electromotor.start(_motor); 
} 

В основной функции я пытаюсь вызвать функцию pornire_motor() для объекта типа SistemPornireCuPreincalzire, но он распечатает сообщение из функции SistemPornire::pornire_motor().

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

class Autoturism { 

private: 
    Electromotor electromotor; 
    Motor motor; 
    SistemPornire sistem_pornire; 
    SistemDirectie sistem_directie; 
    CutieViteze cutieviteze; 

public: 
    Autoturism(SistemPornire&, Electromotor&, Motor&, SistemDirectie&); 
    void porneste_autoturism(); 
    void condu_la_destinatie(); 
    void parcheaza_autoturism(); 
}; 

Autoturism::Autoturism(SistemPornire &sp, Electromotor&e, Motor&m, SistemDirectie&sd): sistem_pornire(sp), electromotor(e), motor(m), sistem_directie(sd) 
{ 

} 

void Autoturism::porneste_autoturism() 
{ 
    std::cout << "Comanda porneste_autoturism a fost trimisa catre sistemul de pornire." << std::endl; 
    this->sistem_pornire.pornire_motor(); 
} 

void Autoturism::condu_la_destinatie() 
{ 
    this->porneste_autoturism(); 
    std::cout << "Odata ce masina a pornit, soferul o poate conduce la destinatie." << std::endl; 

    this->cutieviteze.gearUp(); 
    this->sistem_directie.stanga(0); 
    this->cutieviteze.gearUp(); 
    this->cutieviteze.gearUp(); 
    this->cutieviteze.gearDown(); 
    this->sistem_directie.stanga(90); 
    this->cutieviteze.gearUp(); 
    this->sistem_directie.stanga(0); 
    this->cutieviteze.gearDown(); 
    this->sistem_directie.dreapta(30); 
    this->sistem_directie.dreapta(0); 
    this->sistem_directie.dreapta(10); 


    std::cout << "Odata ce s-a ajuns la destinatie masina e gata de a fi parcata." << std::endl; 
    this->parcheaza_autoturism(); 
    std::cout << "Soferul a ajuns la destinatie." << std::endl; 
} 

void Autoturism::parcheaza_autoturism() 
{ 
    std::cout << "Comanda parcheaza_autoturism a fost trimisa catre sistemul de pornire." << std::endl; 
    this->sistem_pornire.opreste_motor(); 
} 

Основная функция:

int main() 
{ 
    Motor motor; 
    Electromotor electromotor; 
    SistemPornire sistempornire(motor, electromotor); 
    SistemDirectie sistemdirectie; 
    SistemPornireCuPreincalzire sistempornireINC(motor, electromotor); 

    Autoturism masina(sistempornireINC, electromotor, motor,sistemdirectie); 

    std::cout << "Porneste autoturism:" << std::endl; 
    masina.porneste_autoturism(); 

    std::cout << "Parcheaza autoturism:" << std::endl; 
    masina.parcheaza_autoturism(); 

    std::cout << "Condu la destinatie:" << std::endl; 
    masina.condu_la_destinatie(); 
    return 0; 
} 
+3

Я предполагаю, что нарезка объектов. Не может быть уверен без кода вызова. – chris

+9

Можете ли вы построить [минимальный тестовый сценарий] (http://sscce.org), который демонстрирует проблему? –

+0

Показать основную функцию. – Angew

ответ

4

Давайте рассмотрим некоторые части вашего кода и проанализируем, что происходит. Это ваш код от main:

Motor motor; 
Electromotor electromotor; 
SistemPornire sistempornire(motor, electromotor); 
SistemDirectie sistemdirectie; 
SistemPornireCuPreincalzire sistempornireINC(motor, electromotor); 

Обратите внимание, как вы создаете экземпляр SistemPornireCuPreincalzire здесь, которые вы затем передать в конструктор Autoturism:

Autoturism masina(sistempornireINC, electromotor, motor,sistemdirectie); 

Давайте посмотрим на конструктор Autoturism на секунду , А не ___ ли нам?

Autoturism(SistemPornire&, Electromotor&, Motor&, SistemDirectie&); 

Хм, он принимает ссылку к SistemPornire и мы передаем ссылку на SistemPornireCuPreincalzire. Это не обязательно ошибка, но этого достаточно, чтобы заставить вас думать.Итак, давайте посмотрим на то, что делает Autoturism конструктор:

Autoturism::Autoturism(SistemPornire &sp, Electromotor&e, 
         Motor&m, SistemDirectie&sd) 
    : sistem_pornire(sp), electromotor(e), motor(m), sistem_directie(sd) 
{ 

} 

Хмм ... что тип sistem_pornire? Глядя на код, мы видим, что декларируется как:

SistemPornire sistem_pornire; 

Просто видеть этого достаточно, чтобы объяснить, почему виртуальные функции не работают. Тип sistem_pornire известен во время компиляции, и нет виртуальной отправки. Помните, что виртуальные функции выполняются только при вызове виртуальной функции с помощью указателя (т. Е. Вы должны использовать оператор ->).

Но давайте копать немного глубже тоже ...

Так конструктор принимает ссылку на SistemPornire экземпляр и использует его для инициализации экземпляра sistem_pornire элемента в Autoturism. Другими словами, вы копируете объект sistem_pornire с участком SistemPornireSistemPornireCuPreincalzire, который вы заявляете в main.

Объект от main никогда не вызывается и не используется.

Вы должны внимательно прочитать о slicing problem и о virtual functions отправке в C++.

Удачи вам!

3

редактировать

В обновленном вопросе, как @Roddy указывает, нарезка происходит в Autoturism конструктора.

Вы разрезаете свои объекты, назначив производный объект базовому объекту.

SistemPornireCuPreincalzire derived = SistemPornireCuPreincalzire(); 

SistemPornire base = derived; // sliced 

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

SistemPornireCuPreincalzire derived = SistemPornireCuPreincalzire(); 

SistemPornire& base = derived; // no slicing 

См:

+1

Нарезка происходит в конструкторе AutoTurism – Roddy

+0

Существует разрез, но это * не * проблема здесь. –

+0

@NikBougalis Почему нарезка не проблема? –