對象的生存期
1、靜态生存期
• 這種生存期與程式的運作期相同。
• 在檔案作用域中聲明的對象具有這種生存期。
• 在函數内部聲明靜态生存期對象,要冠以關鍵字
static。
2、動态生存期
• 塊作用域中聲明的,沒有用static修飾的對象是動态生存期的對象(習慣稱局部生存期對象)。
• 開始于程式執行到聲明點時,結束于命名該辨別符的作用域結束處。
#include <iostream>
using namespace std;
int i = 1;//i為全局變量,具有靜态生存期
void other(){
static int a = 3;
static int b;
//a,b為靜态局部變量,具有全局壽命,局部可見
//隻第一次進入函數時被初始化
int c = 10;//局部變量,具有動态生存期,每次進入函數時都被初始化
a += 2; i += 32; c += 5;
cout << "---Other---\n";
cout << "i: " << i << "a: " << a << "b: " << b << "c: " << c << endl;
b = a;
}
int main(){
static int a;//靜态局部變量,有全局壽命,局部可見。
int b = -10; // b, c為局部變量,具有動态生存期。
int c = 0;
cout << "‐‐‐MAIN‐‐‐\n";
cout<<" i: "<<i<<" a: "<<a<<" b: "<<b<<" c: "<<c<<endl;
c += 8; other();
cout<<"‐‐‐MAIN‐‐‐\n";
cout<<" i: "<<i<<" a: "<<a<<" b: "<<b<<" c: "<<c<<endl;
i += 10; other();
system("pause");
return 0;
}
運作結果
![](https://img.laitimes.com/img/__Qf2AjLwojIjJCLyojI0JCLiAzNfRHLGZkRGZkRfJ3bs92YsYTMfVmepNHL6dGRPRzZU90MNpHW4Z0MMBjVtJWd0ckW65UbM5WOHJWa5kHT20ESjBjUIF2X0hXZ0xCMx81dvRWYoNHLrdEZwZ1Rh5WNXp1bwNjW1ZUba9VZwlHdssmch1mclRXY39CXldWYtlWPzNXZj9mcw1ycz9WL49zZuBnL0cTNyEDN0ATM4ETMxkTMwIzLc52YucWbp5GZzNmLn9Gbi1yZtl2Lc9CX6MHc0RHaiojIsJye.png)
類的靜态成員
1、靜态資料成員
▫ 用關鍵字static聲明
▫ 該類的所有對象維護該成員的同一個拷貝,靜态資料成員具有靜态生存期。
▫ 必須在類外定義和初始化,用(::)來指明所屬的類。
#include <iostream>
using namespace std;
class Point { //Point類定義
public: //外部接口
Point(int x = 0, int y = 0) : x(x), y(y) { //構造函數
//在構造函數中對count累加,所有對象共同維護同一個count
count++;
}
Point(Point &p) {//拷貝構造函數
x = p.x;
y = p.y;
count++;
}
~Point() { count--; }
int getX() { return x; }
int getY() { return y; }
void showCount() { //輸出靜态資料成員
cout << " Object count = " << count << endl;
}
private: //私有資料成員
int x, y;
static int count;//靜态資料成員聲明,用于記錄點的個數
};
int Point::count = 0;//靜态資料成員定義和初始化,使用類名限定
int main() {//主函數
Point a(4, 5); //定義對象a,其構造函數回使count增1
cout << "Point A: " << a.getX() << ", " << a.getY();
a.showCount(); //輸出對象個數
Point b(a); //定義對象b,其構造函數回使count增1
cout << "Point B: " << b.getX() << ", " << b.getY();
b.showCount(); //輸出對象個數
system("pause");
return 0;
}
運作結果
2、靜态函數成員
▫ 類外代碼可以使用類名和作用域操作符來調用靜态成員函數。
▫ 靜态成員函數隻能引用屬于該類的靜态資料成員或靜态成員函數。
#include <iostream>
using namespace std;
class Point { //Point類定義
public: //外部接口
Point(int x = 0, int y = 0) : x(x), y(y) { //構造函數
//在構造函數中對count累加,所有對象共同維護同一個count
count++;
}
Point(Point &p) { //拷貝構造函數
x = p.x;
y = p.y;
count++;
}
~Point() { count--; }
int getX() { return x; }
int getY() { return y; }
static void showCount() { //靜态函數成員
cout << " Object count = " << count << endl;
}
private: //私有資料成員
int x, y;
static int count;//靜态資料成員聲明,用于記錄點的個數
};
int Point::count = 0;//靜态資料成員定義和初始化,使用類名限定
int main() {//主函數
Point a(4, 5); //定義對象a,其構造函數回使count增1
cout << "Point A: " << a.getX() << ", " << a.getY();
Point::showCount(); //輸出對象個數
Point b(a); //定義對象b,其構造函數回使count增1
cout << "Point B: " << b.getX() << ", " << b.getY();
Point::showCount(); //輸出對象個數
system("pause");
return 0;
}
(注意對比之前的代碼,主要關注靜态函數的調用方式與靜态函數隻能調用靜态資料成員)
類的友元
• 友元是C++提供的一種破壞資料封裝和資料隐藏的機制。
• 通過将一個子產品聲明為另一個子產品的友元,一個子產品能夠引用到另一個子產品中本是被隐藏的資訊。
• 可以使用友元函數和友元類。
• 為了確定資料的完整性,及資料封裝與隐藏的原則,建議盡量不使用或少使用友元。
1、友元函數
• 友元函數是在類聲明中由關鍵字friend修飾說明的非成員函數,在它的函數體中能夠通過對象名通路private 和protected成員
• 作用:增加靈活性,使程式員可以在封裝和快速性方面做合理選擇。
• 通路對象中的成員必須通過對象名。
#include <iostream>
#include <cmath>
class Point { //Point類聲明
public: //外部接口
Point(int x=0, int y=0) : x(x), y(y) { }
int getX() { return x; }
int getY() { return y; }
friend float dist(Point &a, Point &b);
private: //私有資料成員
int x, y;
};
float dist( Point& a, Point& b) {
double x = a.x ‐ b.x;
double y = a.y ‐ b.y;
return static_cast<float>(sqrt(x * x + y *
y));
}
int main() {
Point p1(1, 1), p2(4, 5);
cout <<"The distance is: ";
cout << dist(p1, p2) << endl;
return 0;
}
2、友元類
• 若一個類為另一個類的友元,則此類的所有成員都能通路對方類的私有成員。
• 聲明文法:将友元類名在另一個類中使用friend修飾說明。
友元關系是單向的
如果聲明B類是A類的友元,B類的成員函數就可以通路A類的私有和保護資料,但A類的成員函數卻不能通路B類的私有、保護資料。
共享資料的保護
1、常對象:常類型的對象必須進行初始化,而且不能被更新。
• 常對象:必須進行初始化,不能被更新。
const 類名 對象名
• 常引用:被引用的對象不能被更新。
const 類型說明符 &引用名
• 常數組:數組元素不能被更新。
類型說明符 const 數組名[大小]…
• 常指針:指向常量的指針。
2、用const修飾的對象成員
• 常成員函數
▫ 使用const關鍵字說明的函數。
▫ 常成員函數不更新對象的資料成員。
▫ 常成員函數說明格式:
類型說明符函數名(參數表)const;
這裡,const是函數類型的一個組成部分,是以在實作部分也要帶const關鍵字。
▫ const關鍵字可以被用于參與對重載函數的區分
• 通過常對象隻能調用它的常成員函數。
• 常資料成員
▫ 使用const說明的資料成員。
3、常引用
• 如果在聲明引用時用const修飾,被聲明的引用就是常引用。
• 常引用所引用的對象不能被更新。
• 如果用常引用做形參,便不會意外地發生對實參的更改。常引用的聲明形式如下:
▫ const 類型說明符&引用名;
float dist(const Point &p1, const Point &p2) {
double x = p1.x ‐ p2.x;
double y = p1.y ‐ p2.y;
return static_cast<float>(sqrt(x * x + y *
y));
補充
外部變量與外部函數
• 如果一個變量除了在定義它的源檔案中可以使用外,還能被其它檔案使用,那麼就稱這個變量是外部變量。
• 檔案作用域中定義的變量,預設情況下都是外部變量,但在其它檔案中如果需要使用這一變量,需要用extern關鍵字加以聲明。
• 在所有類之外聲明的函數(也就是非成員函數),都是具有檔案作用域的。
• 這樣的函數都可以在不同的編譯單元中被調用,隻要在調用之前進行引用性聲明(即聲明函數原型)即可。也可以在聲明函數原型或定義函數時用extern修飾,其效果與不加修飾的預設狀态是一樣的。
編譯預處理
• #include 包含指令
▫ 将一個源檔案嵌入到目前源檔案中該點處。
▫ #include<檔案名>
按标準方式搜尋,檔案位于C++系統目錄的include子目錄下
▫ #include"檔案名"
首先在目前目錄中搜尋,若沒有,再按标準方式搜尋。
• #define 宏定義指令
▫ 定義符号常量,很多情況下已被const定義語句取代。
▫ 定義帶參數宏,已被内聯函數取代。
• #undef
▫ 删除由#define定義的宏,使之不再起作用。