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

2番目のクラス:

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

2 に答える 2

5

コードの一部を見て、何が起こっているのかを分析してみましょう。これは からのコードですmain:

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

SistemPornireCuPreincalzirehere のインスタンスを作成し、それを のコンストラクターに渡す方法に注意してくださいAutoturism

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

のコンストラクタを少し見てみましょうAutoturism

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

うーん、それは aへの参照を取り、 への参照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_pornireAutoturismsistem_pornireSistemPornireSistemPornireCuPreincalziremain

オブジェクト frommainは、呼び出されたり使用されたりすることはありません。

スライシングの問題と、C++ での仮想関数のディスパッチについて注意深く読む必要があります。

幸運を!

于 2013-03-12T22:30:48.150 に答える
3

編集

更新された質問では、@Roddy が指摘しているように、Autoturismコンストラクターでスライスが発生します。

派生オブジェクトをベース オブジェクトに割り当てることによって、オブジェクトをスライスしています。

SistemPornireCuPreincalzire derived = SistemPornireCuPreincalzire();

SistemPornire base = derived; // sliced

参照によって派生クラスを参照する必要があります。

SistemPornireCuPreincalzire derived = SistemPornireCuPreincalzire();

SistemPornire& base = derived; // no slicing

見る:

于 2013-03-12T22:02:31.817 に答える