面向對象程序設計課堂筆記
對靜態成員的理解
在之前的學習過程中我們已經瞭解到模塊數據的共享與保護機制,比如:數據成員對外不公開,對象裏定義的變量也具有作用域等等。
對於一個類,函數成員是所有的對象相同的,而數據成員則是各自不同的。如果這時候我們引入了一個新的數據成員,對於所有的對象來說,他的值都是相同的,此時再去對每一個對象定義一次此數據成員則顯得冗雜。由此,我們引入了靜態數據成員。
根據上一段的解釋,可以看出靜態數據成員的簡單定義:是類共有的數據,類的所有成員都維護這一個數據。
在代碼中這樣定義:
class A{
private:
int b;///一般數據成員
static int exnum;///靜態數據成員
}
對於程序中的模塊,都會在內存中佔據一定的存儲空間,那麼靜態數據成員exnum又是如何存儲的呢?
因爲靜態數據成員是類共有的成員,所以他不會佔用對象的存儲空間。可以結合下面的代碼進行理解:
#include<bits/stdc++.h>
using namespace std;
class A{
private:
int b;
static int exnum;
};
int main(){
A a;
cout<<sizeof(A)<<endl;
cout<<sizeof(a)<<endl;
return 0;
}
運行結果如圖:
因爲int類型的b在內存中佔四個字節,也就說明了exnum並沒有存儲在對象a中。
具體有關的理解的博客:傳送門
變量在使用前都需要初始化,這個也不例外。初始化的語法如下:
int A::exnum=0;
其中“::”是預作用符,表示後面的操作對象屬於哪個類。
定義一個東西后,我們需要使用,那麼我們如何訪問這一成員呢。
通過之前的學習,我們可以知道下面的方式是可以訪問exnum的:
#include<bits/stdc++.h>
using namespace std;
class A{
private:
int b;
static int exnum;
public:
A(){exnum=exnum+1;}///構造函數
void shownum(){cout<<"當前的生存對象個數爲:"<<exnum<<endl;}
~A(){exnum=exnum-1;}///析構函數
};
int A::exnum=0;
int main(){
A a;
a.shownum();
return 0;
}
以上方式是通過對象來訪問靜態成員,這也就說明了對象具有靜態成員的訪問權。
但是如果我們還沒有構造對象,又該如何訪問呢。
前面靜態數據成員的定義已經指明,靜態成員屬於類,所以我們可以通過通過類名直接訪問。理論上如果exnum是public的,這是可行的,但是exnum是私有的數據成員,由於模塊的安全性,語法並不支持這種操作。
這時候我們希望某些函數的調用也不依賴於對象,就可以再引進一個靜態函數了,與靜態數據成員類似,這一函數也是屬於類,由類直接調用。
代碼如下:
#include<bits/stdc++.h>
using namespace std;
class A{
private:
int b;
static int exnum;
public:
A(){exnum=exnum+1;}///構造函數
static void shownum(){cout<<"當前的生存對象個數爲:"<<exnum<<endl;}
~A(){exnum=exnum-1;}///析構函數
};
int A::exnum=0;
int main(){
A::shownum();
return 0;
}
/* 添加友元,float MyDistance( pb, pe)
sqrt((pe.x - pb.x) * (pe.x - pb.x) + (pe.y - pb.y) * (pe.y - pb.y));
*/
#include <math.h>
#include <iostream>
using namespace std;
class MyPoint{
public:
MyPoint(int ix, int iy):x(ix),y(iy){
cout<<"構造函數"<<endl;
}
void print() {
cout << "(" << x<< "," << y<< ")" << endl;
}
//友元之普通函數
friend double MyDistance( MyPoint& pb,MyPoint& pe);
private:
int x;
int y;
};
double MyDistance( MyPoint& pb,MyPoint& pe){
return sqrt(1.0*(pe.x - pb.x) * (pe.x - pb.x) + 1.0*(pe.y - pb.y) * (pe.y - pb.y));
}
int main()
{
MyPoint pt1(1, 2);
MyPoint pt2(1, 4);
cout << "pt1和pt2之間的距離: " << MyDistance(pt1, pt2) << endl;
return 0;
}
#include <math.h>
#include <iostream>
using namespace std;
//類的前向聲明
class MyLine;
class MyPoint
{
public:
MyPoint(int ix = 0, int iy = 0) :x(ix), y(iy) {cout<<"構造函數"<<endl;}
void print() {
cout << "(" << x<< "," << y<< ")" << endl;
}
//友元類
friend class MyLine;
private:
int x;
int y;
};
class MyLine
{
public:
double MyDistance(MyPoint& pb,MyPoint& pe){
return sqrt(1.0*(pe.x - pb.x) * (pe.x - pb.x) + 1.0*(pe.y - pb.y) * (pe.y - pb.y));
}
void ShowPoint(MyPoint& p){
cout << "(" <<p.x<< "," <<p.y<< ")" << endl;
}
void showLine(MyPoint& pb,MyPoint& pe) {
ShowPoint(pb);
ShowPoint(pe);
}
};
int main(void)
{
MyPoint pt1(1, 2);
MyPoint pt2(3, 4);
MyLine line;
line.showLine(pt1,pt2);
cout << "pt1和pt2之間的距離: " << line.MyDistance(pt1, pt2) << endl;
return 0;
}
未完待續