2013-03-12 177 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 2013-03-12 21:57:42

+9

您能構建一個證明這個問題的[minimal test-case](http://sscce.org)嗎? – 2013-03-12 21:57:50

+0

顯示主要功能。 – Angew 2013-03-12 21:58:03

回答

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對象與您在main中聲明的SistemPornireCuPreincalzireSistemPornire部分。

來自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 2013-03-12 22:13:09

+0

有切片,但這不是*這裏的問題。 – 2013-03-12 22:22:22

+0

@NikBougalis爲什麼切片不是問題? – 2013-03-12 22:41:33