C++靜態成員和友元成員的理解

面向對象程序設計課堂筆記

對靜態成員的理解

在之前的學習過程中我們已經瞭解到模塊數據的共享與保護機制,比如:數據成員對外不公開,對象裏定義的變量也具有作用域等等。

對於一個類,函數成員是所有的對象相同的,而數據成員則是各自不同的。如果這時候我們引入了一個新的數據成員,對於所有的對象來說,他的值都是相同的,此時再去對每一個對象定義一次此數據成員則顯得冗雜。由此,我們引入了靜態數據成員。

根據上一段的解釋,可以看出靜態數據成員的簡單定義:是類共有的數據,類的所有成員都維護這一個數據。

在代碼中這樣定義:

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;
}

未完待續

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章