聲明
學習材料: 侯捷老師 極客band的教程
筆記使用VScode寫markdown
用sublime編譯,因爲VScode對於中文路徑編譯有問題
用csdn來作爲快速圖牀
inline和宏
inline和宏差不多,方法直接寫在定義的地方是inline
會很快,寫在外面用inline關鍵字來標識,具體是否
inline取決於編譯器實現
public,private
數據和私有數據處理一般放在private
public放給外界使用的接口
可以交錯寫,不一定只寫成兩段
構造函數
- 可以默認值,當然其他函數也可以這樣
- 一般使用
complex(double r=0,double i=0):re(r),im(i){}
初始化列 裏面寫,這樣寫得很大氣(在初始化列初始化) - 構建賦值由聲明順序決定
- 沒有返回類型—不過曾經學jni發現是返回類對象的指針
- 可以有多個構造函數,可以重載(常用於構造函數),編譯器會編碼成不同的東西
但是以下兩種會是編譯器不知道怎麼構造而發生衝突
public:
complex(double r = 0, double i = 0)
: re (r), im (i)
{ }
complex () : re(0), im(0) { }
{
// 下面會導致ambiguous
complex a;
complex b();
}
- singleton單例設計模式把構造函數寫在private(老師說暫時不深入)
不帶指針的類和帶指針的類
不帶指針的類多半不用寫析構函數
const member functions(常量成員函數)
不改變數據內容的,就加const關鍵字
一般只是返回數據
不寫會怎樣,看老師的例子,老師說很重要
正規,大師寫法,魯棒性更高
double real () const { return re; }
{
const complex c1(2,1);
// 如果前面方法沒有用const,而你定義的c1是const
// 這樣你使用下面的輸出編譯器會報錯
// 因爲它以爲你可能會改變c1中的值,所以不準
cout<< c1.real();
cout<< c1.imag();
}
pass by value vs. pass by reference
傳值可能在size很大的時候會導致耗時很多
引用就好很多
C語言有指針傳遞
老師說引用的底部其實就是指針 4個字節
當然如果char 1個字節,也可以直接傳值,但是爲了統一
還是用引用比較好
然後就是如果不想別人改變你內容,你可以用
你改了就編譯不過
complex& operator += (const complex&);
return by value vs. return by reference
爲了效率,有些東西要成爲習慣
返回值也儘量使用引用,如上面代碼
如果要返回臨時變量就不能傳引用,因爲臨時變量在
函數結束之後自己會消亡掉
friend(友元)
友元可以取得private成員
朋友雖然打破了封裝,但是可以直接引用數據,
函數調用獲取數據就慢了
相同的class的各個objects互爲友元
class complex{
public:
// 這裏沒有通過函數拿,而是直接拿數據
int func(const complex& param)
{ return param.re + param.im; }
}
老師說檢查學生寫的類注意點
- 數據在private
- 參數儘可能引用,看情況const
- 返回值儘可能引用傳遞
- body本體中應該加const就要加(別人要不要用const都可以了)
- 初始化賦值儘量使用,儘量不要很晚了在{}內賦值
操作符重載1–成員函數_有this
- C++裏面操作符就相當於一個函數,而C語言不是
- 寫個plus函數不好,所以C++容許你重載
+
- 誰調用我,誰就是this(寫代碼看不到this傳參),任何成員函數都隱藏了this
return by reference
傳參者無需知道接收者是以reference形式接收!
傳參者無需知道接收者是以reference形式接收,你可以用reference接收,也可以用值傳遞接收
突然讓我想到上次慘敗的tx面試,函數傳指針和引用有什麼區別,現在看了侯捷老師的講解才知道這麼精妙
就是定義爲指針的話,傳遞者也必須知道自己要傳遞的是指針,而如果是reference的話,傳遞者只需要知道自己傳遞一個對象就行了,絕妙的講解啊
連串賦值
還因爲有連串賦值,所以+=
的返回值不設計成爲void,而是complex&
上面3個小節對應的代碼和圖片看下面
inline complex&
__doapl(complex* ths, const complex& r)
{
...
return *ths;
}
inline complex&
complex::operator += (const complex& r)
{
return __doapl(this,r);
}
{
complex c1(2,1);
complex c2(5);
c2 += c1;
c3 += c2 += c1;
}
操作符重載2–非成員函數_無this
// 這裏 加 的返回值應該是對象,不能傳reference,否則傳出去一個指針,然後內存回收掉了,然後就很奇怪了
// c = a + b;
inline complex
operator + (const complex& x, const complex& y)
{
return complex(real(x) + real(y),
imag(x) + imag(y));
}
臨時對象typename()
臨時對象typename(),生命很短,用完就沒了,上面那個函數中的complex()
就是,臨時
關於直接返回引用的測試代碼
#include<bits/stdc++.h>
using namespace std;
// error: invalid initialization of reference of type 'int&' from expression of type 'const int'
// return a;
// ^
// 我試了一下,發現是不行的啊
// 等下,a變成了const int?!那應該就是說其實return之後應該也可以
// 變成int吧,難道老師說錯了,待會試試複數類的東西吧
// 後面複習的時候突然想到了爲什麼這裏不行了
// 因爲這裏a 已經變成了一個臨時變量了?
// 然後自己嘗試把const去掉,編譯成功了
// 所以就是說接受者const,傳參者隨意
// 但是如果接受者不const,傳參者不能const
// 這就是之前老師說的你設計的函數儘量加const!
// int & zheng(const int& a)
// {
// return a;
// }
// 引用真香!!!!!
int & zheng(int& a)
{
return a;
}
const int & zheng3(const int & a)
{
return a;
}
int zheng2(const int& a)
{
return a;
}
int main(){
int a = 233;
cout<< zheng(a)<<endl;
cout<< zheng2(a)<<endl;
cout<< zheng3(a)<<endl;
return 0;
}
全部講解用到代碼
#ifndef __COMPLEX__
#define __COMPLEX__
// template<typename T>
class complex
{
public:
complex (double r=0, double i=0)
: re (r) ,im (i)
{ }
complex& operator += (const complex&);
double real () const { return re; }
double imag () const { return im; }
private:
double re, im;
friend complex& __doapl (complex*,
const complex&);
};
inline complex&
__doapl(complex* ths, const complex& r)
{
ths->re += r.re;
ths->im += r.im;
return *ths;
}
inline complex &
complex::operator += (const complex & r)
{
return __doapl (this, r);
}
inline complex
operator + (const complex& x, const complex& y)
{
return complex (real(x) + real(y),
imag(x) + imag(y) );
}
inline complex
operator + (const complex& x, double y)
{
return complex (real(x) + y, imag(x));
}
inline complex
operator + (double x, const complex& y)
{
return complex (x + real(y), imag(y));
}
// 因爲不考慮 c1 << cout; 所以無法使用成員函數定義
// 因爲成員函數定義要用對象在左邊
#include <iostream.h>
ostream&
operator << (ostream& os, const complex& x)
{
return os << '(' << real (x) << ','
<< imag (x) << ')';
}
#endif