Виртуальная функция не работает

Первый класс это:

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;
}

2

Решение

Давайте посмотрим на некоторые части вашего кода и проанализируем, что происходит. Это ваш код от 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 объект с SistemPornire часть SistemPornireCuPreincalzire Вы заявляете в main,

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

Вы должны внимательно прочитать о проблема нарезки и о виртуальные функции отправка в C ++.

Удачи!

4

Другие решения

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

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

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

SistemPornireCuPreincalzire derived = SistemPornireCuPreincalzire();

SistemPornire base = derived; // sliced

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

SistemPornireCuPreincalzire derived = SistemPornireCuPreincalzire();

SistemPornire& base = derived; // no slicing

Увидеть:

3

По вопросам рекламы [email protected]