第一堂课是:
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);
}
在main函数中,我试图为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;
}
答案 0 :(得分: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
中声明的SistemPornire
的{{1}}部分复制构造SistemPornireCuPreincalzire
对象。
来自main
的对象永远不会被调用,也永远不会被使用。
您应该仔细阅读C ++中的slicing problem和virtual functions调度。
祝你好运!答案 1 :(得分:3)
修改的
在更新的问题中,正如@Roddy指出的那样,切片发生在Autoturism
构造函数中。
您正在通过将派生对象分配给基础对象来切割对象。
SistemPornireCuPreincalzire derived = SistemPornireCuPreincalzire();
SistemPornire base = derived; // sliced
您需要通过引用引用派生类:
SistemPornireCuPreincalzire derived = SistemPornireCuPreincalzire();
SistemPornire& base = derived; // no slicing
请参阅: