? ? ? ? 下面就來補充一下c++雷和對象最后一點內容.
????????首先先補充一下上一篇博客上c++類和對象(下篇)上-CSDN博客最后學習的靜態成員變量的小練習求1+2+3+...+n_牛客題霸_牛客網 (nowcoder.com)下面就是題解.靈活的運用了靜態成員變量不銷毀的特點,建立數組利用構造函數來完成n次相加.
class A{
public:A(){_sum+=_a;++_a;}static int Getsum(){return _sum;}
private:static int _a;static int _sum;
};
int A::_a=1;
int A::_sum=0;
class Solution {
public:int Sum_Solution(int n) {A arr[n];return arr[0].Getsum();}
};
? ? ? ? 下面我們開始今天的學習.
友元
? ? ? ? 其實在日期類中重載<<,>>操作符是已經使用過友元函數了.下面就讓我們好好的了解一下友元.
????????友元提供了?種突破類訪問限定符封裝的?式,友元分為:友元函數和友元類,在函數聲明或者類聲明的前?加friend,并且把友元聲明放到?個類的里面.
????????友元函數:外部友元函數可訪問類的私有和保護成員,友元函數僅僅是?種聲明,他不是類的成員函數.友元函數可以在類定義的任何地?聲明,不受類訪問限定符限制.只是聲明.且?個函數可以是多個類的友元函數.
? ? ? ? 友元類:如果A是B的友元類,那么A可以訪問B中的私有和保護成員.友元類的關系是單向的,不具有交換性,?如A類是B類的友元,但是B類不是A類的友元.友元類關系不能傳遞,如果A是B的友元, B是C的友元,但是A不是C的友元.(互為友元要聲明和定義分離,不然會有定義在上面的那個找不到下面的成員的問題)
? ? ? ? 雖然友元可以提供便利,但是友元破壞了封裝,所以友元盡量不要多用.
? ? ? ? 一點點相關練習(注釋是我的易錯點)
//要先聲明,不然A不認識B
class B;class A
{friend void Func(A& a, B& b);
public:A(int a1,int a2){_a1 = a1;_a2 = a2;}
private:int _a1 = 0;int _a2 = 0;
};class B
{friend void Func(A& a, B& b);
public:B(int b1){_b1 = b1;}
private:int _b1 = 0;
};void Func(A& a, B& b)
{cout << a._a1 << " " << a._a2 << endl;cout << b._b1<< endl;
}
int main()
{A a= { 5,6 };B b = 2;Func(a, b);return 0;
}
#define _CRT_SECURE_NO_WARNINGS 1
#include<iostream>using namespace std;class A
{friend void Func(A& a);
public:A(int a1, int a2):_a1(a1),_a2(a2){}
private:int _a1 = 0;int _a2 = 1;
};void Func(A&a)
{cout << a._a1 << " " << a._a2 << endl;
}
int main()
{A a= { 5,6 };Func(a);return 0;
}
#define _CRT_SECURE_NO_WARNINGS 1
#include<iostream>using namespace std;class Time
{friend class Date;
public:Time(int hour=8):_hour(hour){}
private:int _hour;
};class Date
{
public:Date(int year = 2025, int month = 3, int day = 19):_year(year), _month(month), _day(day)//,_hour(hour){}void Func(Time& t){cout << t._hour<<endl;cout << Time()._hour << endl;//cout<<_hour<<endl// 會有為識別_hour的報錯//_hour不可以在友元類中直接使用,要先創建出自己類的對象在使用,或用匿名對象來使用才可以//也不可以直接在構造函數中直接用初始化列表來初始化_hour}
private:int _year;int _month;int _day;
};int main()
{Time t;Date d;d.Func(t);return 0;
}
內部類
????????如果?個類定義在另?個類的內部,這個內部類就叫做內部類.內部類是?個獨立的類,跟定義在全局相比,他只是受外部類類域限制和訪問限定符限制,所以外部類定義的對象中不包含內部類.(用sizeof計算時只算自己的類的大小).且內部類默認是外部類的友元類.(內部類可以訪問外部類的成員變量但是外部類卻不能訪問內部類的成員函數).
????????內部類本質也是?種封裝,當A類實現出來主要就是給B類使用,那么可以考慮把A類設計為B的內部類,如果放到private/protected位置,那么A類就是B類的專屬內部類,其他地方都用不了.(主意和友元做區分,友元不受訪問限定符的限制.)
class A
{
public:class B{public:void Fuc(const A&a){cout << a.a1 << " " << a2 << endl;}private:int b = 0;};
private:int a1 = 0;static int a2;
};int main()
{cout << sizeof(A) << endl;A a;//B b;//沒有突破類域所以沒辦法找到B這個類A::B b;b.Fuc(a);return 0;
}
class A
{
public:private:int a1 = 0;static int a2;class B{public:void Fuc(const A& a){cout << a.a1 << " " << a2 << endl;}private:int b = 0;};
};int main()
{cout << sizeof(A) << endl;A a;//B b;//沒有突破類域所以沒辦法找到B這個類//A::B b;//b.Fuc(a);//定義為private后就不能在類外訪問了return 0;
}
匿名對象
? ? ? ? 用 類型(實參) 定義出來的對象叫做匿名對象,而之前我們定義的 類型 對象名(實參) 定義出來的叫有名對象.匿名對象?命周期只在當前一行,即用即銷毀.(在向鏈表/順序表中插入數據時很好用).
? ? ? ? 一點點相關代碼
class A
{
public:A(int a = 0):_a(a){cout << "A(int a)" << endl;}~A(){cout << "~A()" << endl;}
private:int _a;
};
int main()
{A(1);return 0;
}
對象拷貝時的編譯器優化(了解)
????????現代編譯器會為了盡可能提?程序的效率,在不影響正確性的情況下會盡可能減少?些傳參和傳返 回值的過程中可以省略的拷?,但是在c++標準中卻沒有定義如何優化.一般看編譯器,下面簡單的了解下幾種適中的編譯器優化.(通常會比下面說的更優化)
? ? ? ? 1.傳值傳參下同一行中連續的構造+拷貝構造->直接構造
? ? ? ? 2.傳值返回,連續構造+拷貝構造->直接構造
?????????????????????????? ??
? ? ? ? 以上就是我所學習的類和對象的全部內榮啦,類和對象暫時告一段落了.大家晚安