1. 程式人生 > >5.4-day04-C++拷貝建構函式/靜態成員

5.4-day04-C++拷貝建構函式/靜態成員

一、拷貝建構函式和拷貝賦值運算子 1.拷貝構造:用一個已有的物件,構造和它同類型的副本物件——克隆。 2.形如 class X {   X (const X& that) { ... } }; 的建構函式成為拷貝建構函式。如果一個類沒有定義拷貝建構函式,系統會提供一個預設拷貝建構函式。預設拷貝建構函式對於基本型別的成員變數,按位元組複製,對於類型別的成員變數,呼叫相應型別的拷貝建構函式。 3.在某些情況就下,預設拷貝建構函式只能實現淺拷貝,如果需要獲得深拷貝的複製效果,就需要自己定義拷貝建構函式。 4.形如 class X {   X& operator= (const X& that) {     ...   } }; 的成員函式稱為拷貝賦值運算子函式。如果一個類沒有定義拷貝賦值運算子函式,系統會提供一個預設拷貝賦值運算子函式。預設拷貝賦值運算子函式對於基本型別的成員變數,按位元組複製,對於類型別的成員變數,呼叫相應型別的拷貝賦值運算子函式。 5.在某些情況就下,預設拷貝賦值運算子函式只能實現淺拷貝,如果需要獲得深拷貝的複製效果,就需要自己定義拷貝賦值運算子函式。 練習:實現一個簡化版的字串類String支援: 1.用字元指標形式的字串構造 2.拷貝構造和拷貝賦值 3.獲取字元指標形式字串的成員函式,類似string::c_str 說明:不得使用std::string! 二、靜態成員 1.靜態成員變數和靜態成員函式是屬於類的而非屬於物件。 2.靜態成員變數,為多個物件所共享,只有一份例項,可以通過物件訪問也可以通過類訪問,必須在類的外部定義並初始化。靜態成員變數本質上與全域性變數並沒有區別,只是多了類作用域的約束,和訪控屬性的限制。 class Account { private:   string m_name;   double m_balance;   static double m_rate; }; 3.靜態成員函式,沒有this指標,無法訪問非靜態成員。 4.單例模式 三、成員指標 Student s; string* p = &s.m_name; // 不是 Student s2; (一)成員變數指標 1.定義 成員變數型別 類名::*指標變數名; string Student::*pname; int Student::*page; 2.初始化/賦值 指標變數名 = &類名::成員變數名 pname = &Student::m_name; page = &Student::m_age; 3.解引用 物件.*指標變數名 物件指標->*指標變數名 Student s, *p = &s; s.*pname = "張飛"; cout << p->*page << endl; (二)成員函式指標 1.定義 成員函式返回型別 (類名::*指標變數名) (引數表) void (Student::*plearn) (const string&) const; 2.初始化/賦值 指標變數名 = &類名::成員函式名; plearn = &Stduent::learn; 3.解引用 (物件.*指標變數名) (實參表); (物件指標->*指標變數名) (實參表); (s.*plearn) ("C++"); (p->*plearn) ("UNIX"); 第三課  操作符過載 複數:3+4i Complex c1 - (c2 + c3) c1.sub (c2.add (c3))  一、操作符標記和操作符函式 1.雙目操作符:L#R 成員函式形式:L.operator# (R) 左調右參 全域性函式形式:::operator# (L, R) 左一右二 2.單目操作符:#O/O# 成員函式形式:O.operator# () 全域性函式形式:::operator# (O) 3.三目操作符:不考慮 二、雙目操作符 1.+/-/*// 運算元在計算前後不變。 表示式的值是右值。

complex.cpp
   
  1. #include <iostream>
  2. using namespace std;
  3. class Complex {
  4. public:
  5. Complex (int r = 0, int i = 0) :
  6. m_r (r), m_i (i) {}
  7. void print (void) const {
  8. cout << m_r << '+' << m_i << 'i' << endl;
  9. }
  10. // 第一個const:返回右值
  11. // 第二個const:支援常量型右運算元
  12. // 第三個const:支援常量型左運算元
  13. const Complex operator+ (
  14. const Complex& r) const {
  15. return Complex (m_r + r.m_r, m_i + r.m_i);
  16. }
  17. private:0
  18. int m_r;
  19. int m_i;
  20. friend const Complex operator- (const Complex&,
  21. const Complex&);
  22. };
  23. const Complex operator- (const Complex& l,
  24. const Complex& r) {
  25. return Complex (l.m_r - r.m_r, l.m_i - r.m_i);
  26. }
  27. int main (void) {
  28. const Complex c1 (1, 2);
  29. c1.print ();
  30. const Complex c2 (3, 4);
  31. Complex c3 = c1 + c2; // c3 = c1.operator+ (c2)
  32. c3.print
    (); // 4+6i
  33. // (c1 + c2) = c3;
  34. c3 = c2 - c1; // c3 = ::operator- (c2, c1)
  35. c3.print (); // 2+2i
  36. return 0;
  37. }

hungry.cpp
   
  1. #include <iostream>
  2. using namespace std;
  3. // 餓漢方式
  4. class Singleton {
  5. public:
  6. static Singleton& getInst (void) {
  7. return s_inst;
  8. }
  9. private:
  10. Singleton (void) {}
  11. Singleton (const Singleton&);
  12. static Singleton s_inst;
  13. };
  14. Singleton Singleton::s_inst;
  15. int main (void) {
  16. Singleton& s1 = Singleton::getInst ();
  17. Singleton& s2 = Singleton::getInst ();
  18. Singleton& s3 = Singleton::getInst ();
  19. cout << &s1 << ' ' << &s2 << ' ' << &s3 << endl;
  20. return 0;
  21. }
 
integer.cpp
   
  1. #include <iostream>
  2. using namespace std;
  3. class Integer {
  4. public:
  5. Integer (int data = 0) : m_data (data) {}
  6. void print (void) const {
  7. cout << m_data << endl;
  8. }
  9. /*
  10. Integer (const Integer& that) :
  11. m_data (that.m_data) {
  12. cout << "拷貝構造" << endl;
  13. }
  14. */
  15. private:
  16. int m_data;
  17. };
  18. void foo (Integer i) {
  19. i.print ();
  20. }
  21. Integer bar (void) {
  22. Integer i;
  23. return i;
  24. }
  25. int main (void) {
  26. Integer i1 (10);
  27. i1.print ();
  28. Integer i2 (i1); // 拷貝構造
  29. i2.print ();
  30. Integer i3 = i1; // 拷貝構造
  31. i3.print ();
  32. // Integer i4 (10, 20);
  33. cout << "呼叫foo()函式" << endl;
  34. foo (i1);
  35. cout << "呼叫bar()函式" << endl;
  36. Integer i4 (bar ());
  37. return 0;
  38. }
 
integer2.cpp
   
  1. #include <iostream>
  2. using namespace std;
  3. class Integer {
  4. public:
  5. Integer (int data) : m_data (new int (data)) {}
  6. ~Integer (void) {
  7. if (m_data) {
  8. delete m_data;
  9. m_data = NULL;
  10. }
  11. }
  12. void print (void) const {
  13. cout << *m_data << endl;
  14. }

  15. Integer (const Integer& that) :
  16. m_data (new int (*that.m_data)) {}
  17. void set (int data) {
  18. *m_data = data;
  19. }
  20. Integer& operator= (const Integer& that) {
  21. // 防止自賦值
  22. if (&that != this) {
  23. // 釋放舊資源
  24. delete m_data;
  25. // 分配新資源
  26. m_data = new int (*that.m_data);
  27. // 拷貝新資料
  28. }
  29. // 返回自引用
  30. return *this;
  31. }
  32. private:
  33. int* m_data;
  34. };
  35. int main (void) {
  36. Integer i1 (10);
  37. i1.print ();
  38. Integer i2 (i1);
  39. i2.print ();
  40. i2.set (20);
  41. i2.print ();
  42. i1.print ();
  43. Integer i3 (30);
  44. i3.print (); // 30
  45. i3 = i1; // 拷貝賦值
  46. // i3.operator= (i1);
  47. i3.print (); // 10
  48. i3.set (40);
  49. i3.print (); // 40
  50. i1.print (); // 10
  51. /*
  52. int a = 10, b = 20, c = 30;
  53. (a = b) = c;
  54. cout << a << endl;
  55. */
  56. (i3 = i1) = i2;
  57. // i3.operator=(i1).operator=(i2);
  58. i3.print ();
  59. i3 = i3;
  60. i3.print ();
  61. return 0;
  62. }
 
lazy.cpp
   
  1. #include <iostream>
  2. using namespace std;
  3. // 懶漢方式
  4. class Singleton {
  5. public:
  6. static Singleton& getInst (void) {
  7. if (! m_inst)
  8. m_inst = new Singleton;
  9. ++m_cn;
  10. return *m_inst;
  11. }
  12. void releaseInst (void) {
  13. if (m_cn && --m_cn == 0)
  14. delete this;
  15. }
  16. private:
  17. Singleton (void) {
  18. cout << "構造:" << this << endl;
  19. }
  20. Singleton (const Singleton&);
  21. ~Singleton (void) {
  22. cout << "析構:" << this << endl;
  23. m_inst = NULL;
  24. }
  25. static Singleton* m_inst;
  26. static unsigned int m_cn;
  27. };
  28. Singleton* Singleton::m_inst = NULL;
  29. unsigned int Singleton::m_cn = 0;
  30. int main (void) {
  31. Singleton& s1 = Singleton::getInst ();
  32. Singleton& s2 = Singleton::getInst ();
  33. Singleton& s3 = Singleton::getInst ();
  34. cout << &s1 << ' ' << &s2 << ' ' << &s3 << endl;
  35. s3.releaseInst ();
  36. s2.releaseInst ();
  37. s1.releaseInst ();
  38. return 0;
  39. }

memptr.cpp
   
  1. #include <iostream>
  2. #include <cstring>
  3. using namespace std;
  4. class Student {
  5. public:
  6. Student (const string& name, int age) :
  7. m_name (name), m_age (age) {}
  8. double m_weight;
  9. string m_name;
  10. int m_age;
  11. void learn (const string& lesson) const {
  12. cout << "我在學" << lesson << endl;
  13. }
  14. static void hello (void) {
  15. cout << "你好!" << endl;
  16. }
  17. };
  18. int main (void) {
  19. string Student::*pname = &Student::m_name;
  20. void* pv;
  21. memcpy (&pv, &pname, 4);
  22. cout << pv << endl;
  23. int Student::*page = &Student::m_age;
  24. memcpy (&pv, &page, 4);
  25. cout << pv << endl;
  26. Student s ("張飛", 25), *p = &s;
  27. cout << s.*pname << endl;
  28. cout << p->*page << endl;
  29. Student s2 ("趙雲", 22);
  30. cout << s2.*pname << endl;
  31. void (Student::*plearn) (const string&) const =
  32. &Student::learn;
  33. (s.*plearn) ("C++");
  34. (p->*plearn) ("UNIX");
  35. void (*phello) (void) = Student::hello;
  36. phello ();
  37. return 0;
  38. }
 
private.cpp
   
  1. #include <iostream>
  2. using namespace std;
  3. class Nocopy {
  4. public:
  5. Nocopy (void) {}
  6. private:
  7. Nocopy (const Nocopy&);
  8. Nocopy& operator= (const Nocopy&);
  9. };
  10. void foo (ostream os) {
  11. os << "Hello, World !" << endl;
  12. }
  13. int main (void) {
  14. Nocopy n1;
  15. Nocopy n2 = n1;
  16. Nocopy n3;
  17. n3 = n1;
  18. foo (cout);
  19. return 0;
  20. }
 

static.cpp
   
  1. #include <iostream>
  2. using namespace std;
  3. class A {
  4. public:
  5. static int m_i;
  6. static void foo (void) {
  7. cout << "foo:" << m_i << endl;
  8. // m_d = 3.14;
  9. // bar ();
  10. }cd
  11. double m_d;
  12. void bar (void) {
  13. m_i = 1000;
  14. foo ();
  15. }
  16. };
  17. int A::m_i = 1;
  18. int main (void) {
  19. A::m_i = 10;
  20. A a1, a2;
  21. cout << ++a1.m_i << endl;
  22. cout << a2.m_i << endl;
  23. A::foo ();
  24. a1.foo ();
  25. a1.bar ();
  26. return 0;
  27. }
 
string.cpp
   
  1. #include <iostream>
  2. #include <cstring>
  3. ::using namespace std;
  4. class String {
  5. public:
  6. String (const char* str = NULL) {
  7. m_str = new char[strlen(str?str:"")+1];
  8. strcpy (m_str, str ? str : "");
  9. }
  10. ~String (void) {
  11. if (m_str) {
  12. delete[] m_str;
  13. m_str = NULL;
  14. }
  15. }
  16. String (const String& that) :
  17. m_str (strcpy (
  18. new char[strlen(that.m_str)+1],
  19. that.m_str)) {}
  20. /* 菜鳥
  21. void operator= (const String& that) {
  22. m_str = new char[strlen(that.m_str)+1];
  23. strcpy (m_str, that.m_str);
  24. }*/
  25. String& operator= (const String& that) {
  26. if (&that != this) {
  27. /* 小鳥
  28. delete[] m_str;
  29. m_str = new char[strlen(that.m_str)+1];
  30. strcpy (m_str, that.m_str);
  31. */
  32. /* 大鳥
  33. char* str =
  34. new char[strlen(that.m_str)+1];
  35. delete[] m_str;
  36. m_str = strcpy (str, that.m_str);
  37. */
  38. // 老鳥
  39. String temp (that);
  40. swap (m_str, temp.m_str);
  41. }
  42. return *this;
  43. }
  44. const char* c_str (void) const {
  45. return m_str;
  46. }
  47. private:
  48. char* m_str;
  49. };
  50. int main (void) {
  51. String s1 ("Hello, World !");
  52. cout << s1.c_str () << endl;
  53. String s2 = s1;
  54. cout << s2.c_str () << endl;
  55. String s3 ("Hello, Linux !");
  56. try {
  57. s1 = s3;
  58. }
  59. catch (exception& ex) {
  60. cout << ex.what () << endl;
  61. }
  62. cout << s1.c_str () << endl;
  63. return 0;
  64. }
   拷貝構造:        如果一個類沒有定義拷貝建構函式,系統會提供一個預設拷貝建構函式。預設拷貝建構函式對於基本型別的成員變數,按位元組複製,對於類型別的成員變數,呼叫相應型別的拷貝建構函式。



來自為知筆記(Wiz)