一、this指針
- Human類的屬性fishc與Human()構造器的參數fishc同名,但卻是兩個東西。
- 使用this指針讓構造器知道哪個是參數,哪個是屬性。
this指針:指向當前的類生成的對象
this -> fishc = fishc
?當前對象(this)的屬性(fishc?)?=? 參數 (fishc?)
現在編譯器就懂了,賦值操作符的左邊將被解釋為當前對象的 fishc 屬性,右邊將被解釋為構造器的傳入來的 fishc 參數。
注意:使用 this 指針的基本原則是:如果代碼不存在二義性隱患,就不必使用 this 指針!?
二、類的繼承
C++ 類的繼承允許一個類(派生類 / 子類)獲取另一個類(基類 / 父類)的屬性和方法,實現代碼復用與擴展。
(1)語法:class 子類名:繼承方式 父類名{...}
class Pig:public Animal{...}
?(2)案例
假設我們有一只烏龜和一只豬,它們都有一些共同特征:例如都有嘴巴會吃東西,都睡覺,都看會流口。
當然,它們也有不同的地方:例如烏龜會游泳,豬會爬樹。。。。。。
那么我們就需要編寫一個 Animal 類作為 Turtle類和 Pig 類的基類。
? 基類:?是可以派生出其他的類,也稱為父類或超類。比如這里的 Animal 類是基類。
? 子類:是從基類派生出來的類,比如這里的 Turtle類和 Pig 類是子類。
#include <iostream>
#include <string>//父類
class Animal
{
public:std::string mouth;void eat(); //方法聲明 void sleep();void drool();
};//子類Pig類
class Pig : public Animal
{
public:void climb();
};//子類Turtle類
class Turtle : public Animal
{
public:void swim();
};//方法定義
void Animal::eat()
{std::cout << "I'm eatting!" << std::endl;
}void Animal::sleep()
{std::cout << "I'm sleeping!Don't disturb me!" << std::endl;
}void Animal::drool()
{std::cout << "我是公的,看到母的我會流口水,我正在流口水。。。" << std::endl;
}void Pig::climb()
{std::cout << "我是一個只漂亮的小母豬豬,我會上樹,我正在爬樹,噓。。。" << std::endl;
}void Turtle::swim()
{std::cout << "我是一只小甲魚,當母豬想抓我的時候,我就游到海里。。哈哈。。" << std::endl;
}int main()
{Pig pig;Turtle turtle;pig.eat();turtle.eat();pig.climb();turtle.swim();return 0;
}
(3)繼承方式(public、private、protected)
- 公有繼承(
public
):基類的公有和保護成員在派生類里保持原訪問權限,私有成員不可直接訪問。- 私有繼承(
private
):基類的公有和保護成員在派生類中變為私有成員,基類的私有成員在派生類中仍然不可直接被其他類訪問。- 保護繼承(
protected
):基類的公有和保護成員在派生類中變為保護成員,基類的私有成員在派生類中不可直接被其他類訪問。
鏈接:訪問控制--public、protected、private-CSDN博客?
(4)派生類的構造函數和析構函數 的 執行順序
- 派生類的構造函數會先調用基類的構造函數,然后再執行自身的構造函數體;
- 析構函數的執行順序則相反,先執行派生類的析構函數,再執行基類的析構函數。
#include <iostream>
#include <string>//父類
class BaseClass
{
public:BaseClass(); //父類構造器聲明 ~BaseClass();//父類析構函數聲明 void doSomething();//父類函數聲明
};//子類
class SubClass : public BaseClass
{
public:SubClass();//子類構造器聲明 ~SubClass();//子類析構函數聲明
};
//父類構造函數定義
BaseClass::BaseClass()
{std::cout << "進入基類構造器。。。。。\n";std::cout << "我在基類構造器里邊干了某些事。。。。\n\n";
}
//父類析構函數定義
BaseClass::~BaseClass()
{std::cout << "進入基類析構器.......\n";std::cout << "我在基類析構器里邊也干了某些事。。。。\n\n";
}
//父類函數聲明
void BaseClass::doSomething()
{std::cout << "我干了某些事。。。。\n\n";
}
//子類構造函數定義
SubClass::SubClass()
{std::cout << "進入子類構造器.....\n";std::cout << "我在子類構造器里邊還干了某些事.....\n\n";
}
//子類析構函數定義
SubClass::~SubClass()
{std::cout << "進入子類析構器......\n";
}int main()
{SubClass subclass;subclass.doSomething();std::cout << "完事,收工!\n";return 0;
}
(5)帶有參數的構造器的繼承?
定義子類構造函數時:
Animal::Animal( std::string theName ){name = theName; } Pig::Pig( std::string theName ) : Animal( theName ){ }
#include <iostream>
#include <string>class Animal
{
public:std::string mouth;std::string name;//名字 Animal(std::string theName); //父類有參構造器 聲明 void eat();void sleep();void drool();
};class Pig : public Animal
{
public:void climb();Pig(std::string theName); //Pig子類有參構造器 聲明
};class Turtle : public Animal
{
public:void swim();Turtle(std::string theName); //Turtle子類有參構造器
};
//父類有參構造函數定義
Animal::Animal(std::string theName)
{name = theName;
}void Animal::eat()
{std::cout << "I'm eatting!" << std::endl;
}void Animal::sleep()
{std::cout << "I'm sleeping!Don't disturb me!" << std::endl;
}void Animal::drool()
{std::cout << "我是公的,看到母的我會流口水,我正在流口水。。。" << std::endl;
}
//Pig子類有參構造函數定義
Pig::Pig(std::string theName) : Animal(theName) //重點!!!
{
}void Pig::climb()
{std::cout << "我是一個只漂亮的小母豬豬,我會上樹,我正在爬樹,噓。。。" << std::endl;
}
//Turtle子類有參構造函數定義
Turtle::Turtle(std::string theName) : Animal(theName) //重點!!!
{
}void Turtle::swim()
{std::cout << "我是一只小甲魚,當母豬想抓我的時候,我就游到海里。。哈哈。。" << std::endl;
}int main()
{Pig pig("小豬豬");Turtle turtle("小甲魚");std::cout << "這只豬的名字是: " << pig.name << std::endl;std::cout << "每只烏龜都有個偉大的名字: " << turtle.name << std::endl;pig.eat();turtle.eat();pig.climb();turtle.swim();return 0;
}
?注意在子類的構造器定義里的” :Animal(theName)” 語法含義是:
- – 當調用 Pig () 構造器時(以 theName 作為輸入參數), Animal ()構造器也將被調用( theName 輸入參數將傳遞給它)。
- – 于是,當我們調用 Pig pig(“ 小豬豬” ); 將把字符串 “小豬豬” 傳遞給 Pig () 和 Animal (),賦值動作將實際發生在 Animal () 方法里。?
(6)C++ 支持多重繼承,即一個子類可以繼承多個父類。
未完待續。。。