-
辨別符的作用域與可見性
作用域是一個辨別符在程式正文中有效的區域。
作用域分類:
1、函數原型作用域
2、局部作用域(塊作用域)
3、類作用域。
4、檔案作用域。
5、命名空間作用域(後面會學習)
-
函數原型作用域
函數原型中的參數,其作用域始于"(",結束于")"。
例如:
double area(double radius);
-
局部作用域
函數的形參、在塊中聲明的辨別符。
其作用域自聲明處起,限于塊中。
例如:
void fun(int a) {
int b = a;
cin >> b;
if (b > 0) {
int c;
......
}
}
-
類作用域
類的成員具有類作用域,其範圍包括類體和非内聯成員函數的函數體。
如果在類作用域以外通路類的成員,要通過類名(通路靜态成員),或者該類的對象名、對象引用、對象指針(通路非靜态成員)。
-
檔案作用域
不在前述各個作用域中出現的聲明,就具有檔案作用域,這樣聲明的辨別符其作用域開始于聲明點,結束于檔案尾。
-
可見性
可見性是從對辨別符的引用的角度來談的概念。
可見性表示從内層作用域向外層作用域“看”時能看見什麼。
如果辨別在某處可見,就可以在該處引用此辨別符。
如果某個辨別符在外層中聲明,且在内層中沒有同一辨別符的聲明,則該辨別符在内層可見。
對于兩個嵌套的作用域,如果在内層作用域内聲明了與外層作用域中同名的辨別符,則外層作用域的辨別符在内層不可見。
例如:
//5_1.cpp
#include
using namespace std;
int i; //全局變量,檔案作用域
int main() {
i = 5; //為全局變量i指派
{
int i; //局部變量,局部作用域
i = 7;
cout << "i = " << i << endl;//輸出7
}
cout << “i = ” << i << endl;//輸出5
return 0;
}
-
對象的生存期
靜态生存期:
1、這種生存期與程式的運作期相同。
2、在檔案作用域中聲明的對象具有這種生存期。
3、在函數内部聲明靜态生存期對象,要冠以關鍵字static 。
動态生存期:
塊作用域中聲明的,沒有用static修飾的對象是動态生存期的對象(習慣稱局部生存期對象)。
開始于程式執行到聲明點時,結束于命名該辨別符的作用域結束處。
例如:
#include<iostream>
using namespace std;
int i = 1; // i 為全局變量,具有靜态生存期。
void other() {
static int a = 2;
static int b;
// a,b為靜态局部變量,具有全局壽命,局部可見。
//隻第一次進入函數時被初始化。
int c = 10; // C為局部變量,具有動态生存期,
//每次進入函數時都初始化。
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();
return 0;
}
上面程式的運作結果是:
---MAIN---
i: 1 a: 0 b: -10 c: 0
---OTHER---
i: 33 a: 4 b: 0 c: 15
---MAIN---
i: 33 a: 0 b: -10 c: 8
---OTHER---
i: 75 a: 6 b: 4 c: 15
-
類的靜态成員
靜态資料成員:
1、用關鍵字static聲明。
2、為該類的所有對象共享,靜态資料成員具有靜态生存期。
3、必須在類外定義和初始化,用(::)來指明所屬的類。
例如:具有靜态資料成員的Point類:
#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(); //輸出對象個數
return 0;
}
程式的運作結果是:
Point A: 4, 5 Object count=1
Point B: 4, 5 Object count=2
-
靜态函數成員
類外代碼可以使用類名和作用域操作符來調用靜态成員函數。
靜态成員函數主要用于處理該類的靜态資料成員,可以直接調用靜态成員函數。
如果通路非靜态成員,要通過對象來通路。
例如:具有靜态資料、函數成員的Point類:
#include <iostream>
using namespace std;
class Point {
public:
Point(int x = 0, int y = 0) : x(x), y(y) { 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(); //輸出對象個數
return 0;
}
-
類的友元
友元是C++提供的一種破壞資料封裝和資料隐藏的機制。
通過将一個子產品聲明為另一個子產品的友元,一個子產品能夠引用到另一個子產品中本是被隐藏的資訊。
可以使用友元函數和友元類。
為了確定資料的完整性,及資料封裝與隐藏的原則,建議盡量不使用或少使用友元。
友元函數:
友元函數是在類聲明中由關鍵字friend修飾說明的非成員函數,在它的函數體中能夠通過對象名通路 private 和protected成員
作用:增加靈活性,使程式員可以在封裝和快速性方面做合理選擇。
通路對象中的成員必須通過對象名。
例如:利用友元函數計算兩點之間的距離
#include <iostream>
#include <cmath>
using namespace std;
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;
}
友元類:
若一個類為另一個類的友元,則此類的所有成員都能通路對方類的私有成員。
聲明文法:将友元類名在另一個類中使用friend修飾說明。
例如:
class A {
friend class B;
public:
void display() {
cout << x << endl;
}
private:
int x;
};
class B {
public:
void set(int i);
void display();
private:
A a;
};
void B::set(int i) {
a.x=i;
}
void B::display() {
a.display();
};
類的友元關系是單向的:
如果聲明B類是A類的友元,B類的成員函數就可以通路A類的私有和保護資料,但A類的成員函數卻不能通路B類的私有、保護資料。