最美情侣中文字幕电影,在线麻豆精品传媒,在线网站高清黄,久久黄色视频

歡迎光臨散文網(wǎng) 會(huì)員登陸 & 注冊(cè)

程序設(shè)計(jì)與算法(三)C++面向?qū)ο蟪绦蛟O(shè)計(jì) 北京大學(xué) 郭煒

2022-10-02 16:06 作者:siyan_Fang  | 我要投稿

《多喝水》








01~引用:int & r1=a;

“別名”

從一而終, 接下來(lái)的“=”都是賦值含義

一定要初始化

只能引用變量

常引用:const int & a;

不能通過(guò)常引用修改其引用的內(nèi)容,但可通過(guò)其他方式修改被引用的內(nèi)容

?exgcd(int a, int b, &x, &y)里的就是別名

02~const:

相比define有類型檢查,define只是替換

常量指針 const int*p = &n

常量指針可賦值給非常量指針,反過(guò)來(lái)不行(但可強(qiáng)制轉(zhuǎn)換)

防止自己在函數(shù)里改了不應(yīng)修改的內(nèi)容


03~動(dòng)態(tài)內(nèi)存分配:new<->delete

  1. int * P1 = new int; // 動(dòng)態(tài)分配一個(gè)變量
  2. delete p1;
  3. int * P2 = new int[N]; // 一個(gè)數(shù)組
  4. // new返回值類型都是T*
  5. delete []p2;?//中括號(hào)不能忘記,不然分配來(lái)的數(shù)組沒有完全釋放~
  6. int * P3; //不導(dǎo)致int類型的對(duì)象生成
  7. CRectangle * P4; //不導(dǎo)致對(duì)象生成, 不會(huì)調(diào)用構(gòu)造函數(shù)
  8. CRectangle * P4 = new CRectangle(2,4); //調(diào)用構(gòu)造函數(shù)


04~內(nèi)聯(lián)函數(shù)

inline int Max(int a, int b) { 函數(shù)體語(yǔ)句很少 }

編譯時(shí)不生成函數(shù)調(diào)用語(yǔ)句,而是把原函數(shù)直接貼在調(diào)用位置

可執(zhí)行程序的體積略微增大


04~函數(shù)重載

幾個(gè)函數(shù)名稱相同,使得函數(shù)命名變得簡(jiǎn)單

只要參數(shù)表不一樣,就不算重復(fù)定義


04~缺省參數(shù)

void f(int x1, int x2 = 2, int x3 = 3) { }

f(10) //f(10, 2, 3)

f(10, , 8) //error

提高可擴(kuò)充性 void circle(int r, int x, int y, sring color = "black")

注意避免有函數(shù)重載時(shí)的二義性(06~)

05~結(jié)構(gòu)化程序設(shè)計(jì)

不足:沒有封裝和隱藏的概念

具體表現(xiàn)在,函數(shù)和其所操作的數(shù)據(jù)結(jié)構(gòu)沒有直觀的聯(lián)系


05~類和對(duì)象:帶函數(shù)的結(jié)構(gòu)體

封裝、隱藏、抽取重用

解決~函數(shù)跟其操作的數(shù)據(jù)結(jié)構(gòu)沒有直觀聯(lián)系

  1. class CRectangle //自定義類型名 //class換成struct也沒啥~
  2. {
  3. public :
  4. int w, h; //成員變量
  5. // 成員函數(shù)(不屬于對(duì)象里,僅有一份)
  6. int Area(); //算面積 ,函數(shù)內(nèi)容在class之外
  7. int Perimeter() { return 2*(w+h); } //算周長(zhǎng)
  8. void Init(int _w, int _h) { w = _w; h = _h; } //初始化
  9. }; //分號(hào)~
  10. int CRectangle:: int Area() { return w*h; }?//寫在類之外的成員函數(shù)前要加上”類名::“,不然怎么知道對(duì)應(yīng)哪個(gè)類的成員函數(shù)~
  11. int main(void)
  12. {
  13. int w, h;
  14. CRectangle r; //r是對(duì)象(類的實(shí)例),所占用的內(nèi)存空間>=所有成員變量之和
  15. cin >> w >> h;
  16. r.Init(w, h);
  17. cout << r.Area() << endl << r.Perimeter();
  18. return 0;
  19. }

對(duì)象間的運(yùn)算:

可賦值,不能比較,除非重載運(yùn)算符


成員變量和成員函數(shù)的使用:

對(duì)象名.成員名 //上面已經(jīng)用到~

指針->成員名

  1. CRectangle r1, r2;
  2. CRectangle * p1 = & r1, * p2 = & r2;
  3. p1->w = 5;
  4. p2->Init(5, 4);

引用名.成員名

  1. CRectangle & rr = r2;
  2. rr.Init(5, 4);


06~ private和public

成員變量和成員函數(shù)可分開寫

int CRectangle:: int Area() { return w*h; }?

類成員的可訪問(wèn)范圍

- private (默認(rèn))?

- public

- protected (以后再說(shuō))

私有成員變量在主函數(shù)里不能通過(guò)”類名::成員名“訪問(wèn),但可通過(guò)公有成員函數(shù)修改或打印其值(視頻12中有例子)


07~ 構(gòu)造函數(shù):

X::X(所有成員變量對(duì)應(yīng)的參數(shù)) {每個(gè)成員變量都有了自己的值}

名字與類名相同

對(duì)對(duì)象進(jìn)行初始化,自動(dòng)

  1. class Complex {
  2. private :
  3. int real, imag;
  4. public :
  5. Complex(int r, int i = 0);
  6. };
  7. Complex::Complex(int r, int i) {
  8. real = r; imag = i;
  9. }
  10. Complex c1; //error
  11. Complex * pc = new Complex; //error
  12. Complex c1(2); //OK
  13. Complex c1(2, 4); //OK
  14. Complex * pc = new Complex(3, 4); //error

本文03~也中有相關(guān)內(nèi)容~

08~ 復(fù)制構(gòu)造函數(shù)——初始化

X::X( X & 對(duì)象)

X::X( const X & 對(duì)象)

只有一個(gè)參數(shù),且必須是引用——即同類對(duì)象的引用

如果你沒寫復(fù)制構(gòu)造函數(shù),編譯器會(huì)生成默認(rèn)的復(fù)制構(gòu)造函數(shù)(淺拷貝<或叫位拷貝>但我們一般需要深拷貝<或叫值拷貝>)

【總結(jié)】無(wú)參構(gòu)造函數(shù)不一定存在,但復(fù)制構(gòu)造函數(shù)一定存在


起作用的三種情況

Complex c2(c1); //當(dāng)一個(gè)對(duì)象去初始化另一個(gè)對(duì)象時(shí)

上式<=> Complex c2 = c1; //這不是賦值語(yǔ)句,而是初始化語(yǔ)句

【注意】對(duì)象間賦值不導(dǎo)致調(diào)用復(fù)制構(gòu)造函數(shù)?

void f(A a); f(a2); //對(duì)象做參數(shù),這個(gè)形參a被a2初始化——復(fù)制構(gòu)造函數(shù)

【注意】形參不一定是實(shí)參的拷貝,比如當(dāng)你自己寫的復(fù)制構(gòu)造函數(shù)并沒有賦值語(yǔ)句

A f(void); //對(duì)象作返回值,編譯器創(chuàng)建臨時(shí)對(duì)象,臨時(shí)對(duì)象被初始化

【注意】有的編譯器會(huì)進(jìn)行優(yōu)化,省略返回值的臨時(shí)變量

這樣太慢了,所以使用常量(const)引用(&)參數(shù)


09(1)~ 類型轉(zhuǎn)換構(gòu)造函數(shù)

Complex(一個(gè)參數(shù)) {所有成員變量都有了自己的值}


類型轉(zhuǎn)換構(gòu)造函數(shù)特點(diǎn):

1.是構(gòu)造函數(shù)?

2.只有一個(gè)參數(shù)?

3.但不是復(fù)制構(gòu)造函數(shù)

比如Complex初始化需要兩個(gè)參數(shù)i和r,當(dāng)主函數(shù)中寫道“c1 = 9”時(shí),通過(guò)這種函數(shù)把9轉(zhuǎn)化為和Complex對(duì)象格式相同的樣子,視頻中就是(9,0)

“類型轉(zhuǎn)換構(gòu)造函數(shù)”只是一類用法的名字。當(dāng)需要的時(shí)候,編譯器自動(dòng)調(diào)用。


09(2)~ 析構(gòu)函數(shù)

~Complex() {}?

沒有參數(shù)

每個(gè)類僅有一個(gè)

而構(gòu)造函數(shù)每個(gè)類可有多個(gè)(重載)

如果你沒寫析構(gòu)函數(shù),編譯器會(huì)生成析構(gòu)函數(shù)(不做任何操作)


10~ 構(gòu)造/析構(gòu)函數(shù)調(diào)用時(shí)機(jī)

(復(fù)制)構(gòu)造函數(shù):創(chuàng)建新對(duì)象(初始化)

類型轉(zhuǎn)換構(gòu)造函數(shù):如“Complex a = 5; ”編譯器將5轉(zhuǎn)換成臨時(shí)對(duì)象,臨時(shí)對(duì)象把值給a,臨時(shí)對(duì)象再被析構(gòu)

析構(gòu)函數(shù):對(duì)象生命周期結(jié)束(區(qū)分:全局變量、靜態(tài)局部變量、局部變量的生命周期)

【注意】使用new分配來(lái)的對(duì)象只要不delete,就不會(huì)消亡,也就是不被析構(gòu)

函數(shù)參數(shù)傳遞對(duì)象時(shí)(形參列表或函數(shù)返回),如果不是引用,則有兩個(gè)臨時(shí)對(duì)象被創(chuàng)建,形參列表的那一個(gè)在函數(shù)調(diào)用結(jié)束時(shí)被析構(gòu),被返回的那個(gè)臨時(shí)對(duì)象在調(diào)用語(yǔ)句結(jié)束后也被析構(gòu)

備注:有的編譯器為了優(yōu)化,不生成返回值臨時(shí)對(duì)象,就少調(diào)用一對(duì)復(fù)制構(gòu)造函數(shù)和析構(gòu)函數(shù)~


11~ this指針

指向成員函數(shù)所作用的對(duì)象

靜態(tài)成員函數(shù)中不能使用


19~實(shí)例:實(shí)現(xiàn)一個(gè)CArray類(可變長(zhǎng)數(shù)組)(就是vector)

  1. # include <iostream>
  2. # include <cstdio>
  3. using namespace std;
  4. class CArray?
  5. {
  6. int size;
  7. int cnt;
  8. int * ptr;
  9. public:
  10. CArray() //構(gòu)造函數(shù),可以用缺省參數(shù)方法,這樣創(chuàng)建對(duì)象時(shí)如果有規(guī)定大小,寫在括號(hào)里就行啦~
  11. {
  12. size = 2;
  13. cnt = 0;
  14. ptr = new int[2];
  15. printf("構(gòu)造\n");
  16. }
  17. CArray(const CArray & a) //復(fù)制構(gòu)造函數(shù)
  18. {
  19. size = a.size;
  20. cnt = a.cnt;
  21. //自己寫復(fù)制構(gòu)造函數(shù),而不用編譯器缺省出來(lái)的原因是我需要深拷貝
  22. ptr = new int[size];
  23. for (int i = 0; i < cnt; i++)
  24. {
  25. ptr[i] = a.ptr[i];
  26. }
  27. printf("復(fù)制構(gòu)造\n");
  28. }

  29. void operator=(const CArray & a) //返回值最好是&,方便連等
  30. {
  31. //還要避免 a = a
  32. //如果構(gòu)造函數(shù)默認(rèn)size是0的話,空數(shù)組的賦值單獨(dú)寫
  33. //原有空間不夠用時(shí)再分配新空間,效率高
  34. size = a.size;
  35. cnt = a.cnt;
  36. ptr = new int[size];
  37. for (int i = 0; i < cnt; i++)
  38. {
  39. ptr[i] = a.ptr[i];
  40. }
  41. printf("復(fù)制構(gòu)造:運(yùn)算符“=”重載\n");
  42. }
  43. ~CArray() //析構(gòu)函數(shù)
  44. {
  45. delete[]ptr;
  46. printf("析構(gòu)\n");
  47. }

  48. void push_back(int x)
  49. {
  50. if (cnt == size) //放不下了
  51. {
  52. int * oldptr = ptr;
  53. ptr = new int[size * 2];
  54. for (int i = 0; i < size; i++)
  55. {
  56. ptr[i] = oldptr[i];
  57. }
  58. delete[] oldptr;
  59. ptr[size] = x;
  60. cnt++;
  61. size *= 2;
  62. }
  63. else
  64. {
  65. ptr[cnt] = x;
  66. cnt++;
  67. }
  68. return;
  69. }

  70. int length()?
  71. {
  72. return cnt;?
  73. }

  74. int & operator [](int i) //返回類型寫對(duì)啦~ (非引用的返回值不能做左值)
  75. {
  76. return ptr[i];
  77. }
  78. };
  79. int main(void)
  80. {
  81. CArray a, a2, a3;
  82. a.push_back(1); a.push_back(2); a.push_back(3);
  83. a2 = a; // “=”重載的復(fù)制構(gòu)造,為了防止淺拷貝
  84. printf("遍歷a2:%d %d %d\n", a2[0], a2[1], a2[2]); //重載“[]”
  85. a[1] = 5;
  86. printf("遍歷a:%d %d %d\n", a[0], a[1], a[2]);
  87. CArray a4(a);//復(fù)制構(gòu)造函數(shù)
  88. printf("a4現(xiàn)在有%d個(gè)元素\n", a4.length());
  89. printf("遍歷a4:%d %d %d\n", a4[0], a4[1], a4[2]);
  90. return 0;
  91. }
  92. Output:
  93. 構(gòu)造
  94. 構(gòu)造
  95. 構(gòu)造
  96. 復(fù)制構(gòu)造:運(yùn)算符“=”重載
  97. 遍歷a2:1 2 3
  98. 遍歷a:1 5 3
  99. 復(fù)制構(gòu)造
  100. a4現(xiàn)在有3個(gè)元素
  101. 遍歷a4:1 5 3
  102. 析構(gòu)
  103. 析構(gòu)
  104. 析構(gòu)
  105. 析構(gòu)

20~ "<<"和">>"的重載

cout是在iostream中定義的ostream類的對(duì)象

例題:

  1. # include <iostream>
  2. using namespace std;
  3. class Complex
  4. {
  5. public:
  6. int real, imag;
  7. };
  8. ostream & operator << (ostream & o, const Complex & c)
  9. {
  10. o << c.real << "+" << c.imag << "i";
  11. return o;
  12. }
  13. istream & operator >> (istream & i, Complex & c)
  14. {
  15. scanf_s("%d+%di", &c.real, &c.imag);
  16. return i;
  17. }
  18. int main(void)
  19. {
  20. Complex c1, c2;
  21. cin >> c1 >> c2;
  22. cout << c1 << endl << c2 << endl;
  23. return 0;
  24. }

彈幕中的問(wèn)題:既然ostream類已經(jīng)不能再加入新的成員函數(shù),為什么不能把運(yùn)算符重載函數(shù)寫為Complex類的成員函數(shù),而一定要將其寫成全局函數(shù)?

把"<<"重載為Complex類的成員函數(shù)只需要1個(gè)參數(shù)("<<"的目數(shù)減1),那就得寫成下面這個(gè)樣子:

ostream & operator << (ostream & o)

{

o << real << "+" << imag << "i";

return o;

}

但是:

對(duì)雙目運(yùn)算符而言,成員運(yùn)算符重載函數(shù)的形參表中僅有一個(gè)參數(shù),它作為運(yùn)算符的右操作數(shù)。另一個(gè)操作數(shù)(左操作數(shù))是隱含的,是該類的當(dāng)前對(duì)象,它是通過(guò) this 指針隱含地遞給函數(shù)的。(視頻16的08:30——”a運(yùn)算符b“等價(jià)于”a.operator運(yùn)算符b“)

所以只有1個(gè)參數(shù)的形參表沒法寫,所以一定要將"<<"重載函數(shù)寫成全局函數(shù)~


21~ 類型轉(zhuǎn)換運(yùn)算符的重載

opreator double() {return real;} //不寫返回類型

cout << (double)c; //可顯式轉(zhuǎn)換

double n = 2 + c; //可隱式轉(zhuǎn)換


22~ "++" "--" 的重載

為了區(qū)分前置和后置,前置運(yùn)算符視為一元,后置運(yùn)算符視為二元(第二個(gè)形參無(wú)意義隨意寫,但要有)

21、22綜合例子:

  1. # include <iostream>
  2. using namespace std;
  3. class CDemo
  4. {
  5. private:
  6. int n;
  7. public:
  8. CDemo(int _n) { n = _n; }
  9. operator int() { return n; }
  10. friend CDemo & operator++ (CDemo & d);
  11. friend CDemo & operator--(CDemo & d);
  12. friend CDemo operator++ (CDemo & d, int);
  13. friend CDemo operator-- (CDemo & d, int);
  14. ~CDemo() {}
  15. };
  16. CDemo & operator++ (CDemo & d) { d.n++; return d; }//前置加加
  17. CDemo & operator-- (CDemo & d) { d.n--; return d; }
  18. CDemo operator++ (CDemo & d, int) { CDemo tmp(d);?d.n++;?return tmp; }//后置加加 //CDemo tmp(d); 這一句,使用了編譯器缺省的復(fù)制構(gòu)造函數(shù)
  19. CDemo operator-- (CDemo & d, int) { CDemo tmp(d.n);?d.n--;?return tmp; }
  20. int main(void)
  21. {
  22. CDemo d(5);
  23. cout << (d++) << endl;
  24. cout << d << endl;
  25. cout << (++d) << endl;
  26. cout << d << endl; //5677

  27. cout << (d--) << endl;
  28. cout << d << endl;
  29. cout << (--d) << endl;
  30. cout << d << endl; //5677
  31. return 0;
  32. }

【注意】++i和i++在返回值和效率上的差別:

++i:返回是i的引用,且效率高

i++:返回值是臨時(shí)變量,且效率低


【運(yùn)算符重載的總結(jié)】c++不能定義新的運(yùn)算符、重載要符合日常習(xí)慣、重載不改變運(yùn)算符優(yōu)先級(jí)、有些運(yùn)算符不能被重載(點(diǎn)號(hào)、點(diǎn)星、兩冒號(hào)、問(wèn)號(hào)冒號(hào)、sizeof)、有些運(yùn)算符必須聲明為類的成員函數(shù)(小括號(hào)、中括號(hào)、箭號(hào)、賦值等號(hào))

程序設(shè)計(jì)與算法(三)C++面向?qū)ο蟪绦蛟O(shè)計(jì) 北京大學(xué) 郭煒的評(píng)論 (共 條)

分享到微博請(qǐng)遵守國(guó)家法律
吉木萨尔县| 瑞安市| 彰武县| 全州县| 涟源市| 来凤县| 阜阳市| 无棣县| 百色市| 安吉县| 陵川县| 德安县| 虞城县| 昌都县| 凌海市| 东至县| 桃江县| 称多县| 扶风县| 凤冈县| 本溪市| 宝丰县| 河津市| 南召县| 乌兰浩特市| 肇州县| 昌都县| 都昌县| 汉源县| 辰溪县| 望奎县| 北安市| 万盛区| 宾阳县| 钟祥市| 包头市| 饶平县| 大冶市| 西平县| 高安市| 孟津县|