1. 程式人生 > >C++進階--建構函式和解構函式中的虛擬函式

C++進階--建構函式和解構函式中的虛擬函式

//############################################################################
/*
任何時候都不要在建構函式或解構函式中呼叫虛擬函式
*/
class dog {
    public:
        string m_name;
        dog(string name) {m_name = name;  bark();}
        virtual void bark() { cout<< "Woof, I am just a dog " << m_name << endl;}
};

class yellowdog : public dog {
    public:
        yellowdog(string name) : dog(string name) {...}
        virtual void bark() { cout << "Woof, I am a yellow dog " << m_name << endl; }
};

int main ()
{
  yellowdog mydog("Bob");
}


輸出:
Woof, I am just a dog Bob.

/*
在構造的過程中,所有虛擬函式表現為非虛擬函式

為什麼?
基類在派生類之前構造。
所以bark()的時候,yellowdog還沒有構造


為什麼Java中表現不一樣?

Java和C++在定義物件的生命週期上有一個基本的差異
Java: 所有成員在建構函式執行前被null初始化。生命週期在建構函式之前已經開始
C++: 建構函式負責初始化成員。生命週期在建構函式結束之後才開始

呼叫物件中還未被初始化的部分是繼承危險的
呼叫物件中已經被delete的部分也是危險的
*/


/*
解決方法 1:
不使用多型,使用初始化引數來產生執行時差異
*/
class dog {
    public:
        ...
        dog(string name, string color) {m_name = name; bark(color);}
        void bark(string str) { cout<< "Woof, I am "<< str << " dog " << m_name << endl;}
};

class yellowdog : public dog {
    public:
        yellowdog(string name):dog(name, "yellow") {}
};

int main ()
{
  yellowdog mydog("Bob");
}

輸出:
Woof, I am yellow dog Bob


/*
解決方法 2:
使用私有靜態成員函式,不同派生類可執行不同操作
*/
class dog {
    public:
        ...
        dog(string name, string woof) {m_name = name; bark(woof);}
        dog(string name) {m_name = name; bark( getMyColor() );}
        void bark(string str) { cout<< "Woof, I am "<< str << " dog " << m_name << endl;}
    private:
        static string getMyColor() {return "just a";} 
};

class yellowdog : public dog {
    public:
        yellowdog(string name):dog(name, getMyColor()) {}
    private:
        static string getMyColor() {return "yellow";}  //Why static? 
};

int main ()
{
  yellowdog mydog("Bob");
}
OUTPUT:
Woof, I am yellow dog Bob