1. 程式人生 > >《21天C++》筆記之6月27日

《21天C++》筆記之6月27日

另一個 聲明 fast 自由 不支持 stream mem strings 析構函數

繼承

  • 公有繼承,is-a的關系,比如,He is a man;

    派生類可訪問基類非私有成員,派生類實例也是;

  • 私有繼承和保護繼承,has-a的關系,Car has a motor;

    私有繼承,也讓派生類可訪問基類非私有成員,但派生類實例無法訪問基類任何成員,並且派生類的的子類也無法訪問基類任何成員;

    保護繼承,與私有繼承不同的是,子類的子類是可以訪問基類的非私有成員;

註意:僅當必要時才使用私有或保護繼承,遇到has-a情況時,盡量用組合或者聚合的方式替代(即將‘基類對象當作‘子類’‘的一個成員屬性)

class Motor
{
public:
	void SwitchIgnition();
	void PumpFuel();
	void FireCylinders();
};
class Car
{
private:
	Motor heartOfCar;
public:
	void Move()
	{
		heartOfCar.FireCylinders();
		heartOfCar.PumpFuel();
		heartOfCar.SwitchIgnition();
	}
};
  • 切除:將子類對象顯示復制給父類對象,或通過參數傳遞給父類對象,會只保留Base部分,這叫做切除
class Platypus:public Mammal,public Reptile,public Bird{};//多繼承
  • 重載,覆蓋,隱藏:重載就是一個類裏同名不同參數的函數,覆蓋就是子類與父類同名同參數的函數,隱藏就是子類會將父類中同名但不同參數的函數隱藏,即實例不能訪問。

多態

  • 使用虛函數實現多態行為,通過引用或者指針調用虛函數即可實現多態

  將派生類對象視為基類對象,並執行派生類的覆蓋函數

class Fish
{
public:
    virtual void Swim()
    {
        cout 
<< "Fish Swim.." << endl; } }; class Tuna : public Fish { public: virtual void Swim() { cout << "Tuna is fast" << endl; } }; class Carp : public Fish { public: virtual void Swim() { cout << "Carp is slow" << endl; } };
int main() { Tuna t; Carp c; Fish &f1 = t; f1.Swim(); return 0; }
  • 對於使用new在自由存儲區中實例化派生類對象,如果將其付給基類指針,
  • 並通過該指針調用delete,將不會調用派生類的析構函數.
  • 這可能會導致資源未釋放,內存泄露等問題.
  • 要避免這種問題,要將析構函數聲明為虛函數.
class Fish
{
public:
    Fish()
    {
        cout <<"Constructed Fish"<< endl;
    }
    ~Fish()
    {
        cout << "Destroyed Fish" << endl;
    }
};

class Tuna : public Fish
{
public:
    Tuna()
    {
        cout << "Constructed Tuna" <<endl;
    }
    ~Tuna()
    {
        cout << "Destroyed Tuna" << endl;
    }
};

void DeleteFishMemory(Fish *pFish)
{
    delete pFish;
}

int main()
{
    Tuna *pTuna = new Tuna;
    DeleteFishMemory(pTuna);
    return 0;
}
/*輸出:
**Constructed Fish
**Constructed Tuna
**Destroyed Fish
*/

抽象基類與純虛函數

  不能被實例化的基類稱為抽象基類,可通過聲明純虛函數創建.

class Fish
{
public:
	virtual void Swim() = 0;
};

class Tuna : public Fish
{
public:
	void Swim()
	{
		cout << "Tuna swims fast in the sea " << endl;
	}
};

使用虛繼承解決菱形問題,(二義性)

    

class Animal
{
public:
    Animal()
    {
        cout << "ANimal constructor" << endl;
    }

    int Age;
};

class Mammal:public virtual Animal
{

};

class Bird:public virtual Animal
{};

class Reptile:public virtual Animal
{};

class Platypus:public Mammal, public Bird, public Reptile
{
public:
    Platypus()
    {
        cout << "Platypus constructor" <<endl;
    }
};

int main()
{
    Platypus duckBilledp;

    duckBilledp.Age = 25;
    return 0;
}

  • 繼承多個從同一個類派生而來的基類時,如果沒有使用虛繼承,將會繼承多個基類的父類,而使用了虛繼承,則只繼承一個.
  • virtual關鍵字有兩個不同概念,一個是用於多態,另一個是用於虛繼承解決二義性

從技術上說,C++不支持虛復制構造函數

運算符類型與運算符重載

  • 單目運算符

    1, (++)遞增運算符

      Date operator ++ (){} 單目前綴運算符在類中重載

      Date operator ++ (int){}單目後綴運算符在類中重載

    2, 轉換運算符,下例是用轉換運算符將Date轉換為const char*

class Date
{
private:
    int Day;
    int Month;
    int Year;

    string DateInString;
public:
    Date (int InputDay, int InputMonth, int InputYear) : Day(InputDay), Month(InputMonth), Year(InputYear)
    {}

    operator const char*()
    {
        ostringstream formattedDate;
        formattedDate << Day << " / " << Month << " / " << Year;

        DateInString = formattedDate.str();
        return DateInString.c_str();
    }
};

int main()
{
    Date Holiday (25, 12, 2011);
    cout << "Holiday is on: " << Holiday << endl;
    return 0;
}
//結果:Holiday is on: 25 / 12 / 2011

《21天C++》筆記之6月27日