5.4-day04-C++拷貝建構函式/靜態成員
阿新 • • 發佈:2018-11-29
一、拷貝建構函式和拷貝賦值運算子
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
hungry.cpp
integer.cpp
integer2.cpp
lazy.cpp
memptr.cpp
private.cpp
static.cpp
string.cpp
來自為知筆記(Wiz)
complex.cpp
#include <iostream>
using namespace std;
class Complex {
public:
Complex (int r = 0, int i = 0) :
m_r (r), m_i (i) {}
void print (void) const {
cout << m_r << '+' << m_i << 'i' << endl;
}
// 第一個const:返回右值
// 第二個const:支援常量型右運算元
// 第三個const:支援常量型左運算元
const Complex operator+ (
const Complex& r) const {
return Complex (m_r + r.m_r, m_i + r.m_i);
}
private:0
int m_r;
int m_i;
friend const Complex operator- (const Complex&,
const Complex&);
};
const Complex operator- (const Complex& l,
const Complex& r) {
return Complex (l.m_r - r.m_r, l.m_i - r.m_i);
}
int main (void) {
const Complex c1 (1, 2);
c1.print ();
const Complex c2 (3, 4);
Complex c3 = c1 + c2; // c3 = c1.operator+ (c2)
c3.print
(); // 4+6i// (c1 + c2) = c3;
c3 = c2 - c1; // c3 = ::operator- (c2, c1)
c3.print (); // 2+2i
return 0;
}
hungry.cpp
#include <iostream>
using namespace std;
// 餓漢方式
class Singleton {
public:
static Singleton& getInst (void) {
return s_inst;
}
private:
Singleton (void) {}
Singleton (const Singleton&);
static Singleton s_inst;
};
Singleton Singleton::s_inst;
int main (void) {
Singleton& s1 = Singleton::getInst ();
Singleton& s2 = Singleton::getInst ();
Singleton& s3 = Singleton::getInst ();
cout << &s1 << ' ' << &s2 << ' ' << &s3 << endl;
return 0;
}
integer.cpp
#include <iostream>
using namespace std;
class Integer {
public:
Integer (int data = 0) : m_data (data) {}
void print (void) const {
cout << m_data << endl;
}
/*
Integer (const Integer& that) :
m_data (that.m_data) {
cout << "拷貝構造" << endl;
}
*/
private:
int m_data;
};
void foo (Integer i) {
i.print ();
}
Integer bar (void) {
Integer i;
return i;
}
int main (void) {
Integer i1 (10);
i1.print ();
Integer i2 (i1); // 拷貝構造
i2.print ();
Integer i3 = i1; // 拷貝構造
i3.print ();
// Integer i4 (10, 20);
cout << "呼叫foo()函式" << endl;
foo (i1);
cout << "呼叫bar()函式" << endl;
Integer i4 (bar ());
return 0;
}
integer2.cpp
#include <iostream>
using namespace std;
class Integer {
public:
Integer (int data) : m_data (new int (data)) {}
~Integer (void) {
if (m_data) {
delete m_data;
m_data = NULL;
}
}
void print (void) const {
cout << *m_data << endl;
}
Integer (const Integer& that) :
m_data (new int (*that.m_data)) {}
void set (int data) {
*m_data = data;
}
Integer& operator= (const Integer& that) {
// 防止自賦值
if (&that != this) {
// 釋放舊資源
delete m_data;
// 分配新資源
m_data = new int (*that.m_data);
// 拷貝新資料
}
// 返回自引用
return *this;
}
private:
int* m_data;
};
int main (void) {
Integer i1 (10);
i1.print ();
Integer i2 (i1);
i2.print ();
i2.set (20);
i2.print ();
i1.print ();
Integer i3 (30);
i3.print (); // 30
i3 = i1; // 拷貝賦值
// i3.operator= (i1);
i3.print (); // 10
i3.set (40);
i3.print (); // 40
i1.print (); // 10
/*
int a = 10, b = 20, c = 30;
(a = b) = c;
cout << a << endl;
*/
(i3 = i1) = i2;
// i3.operator=(i1).operator=(i2);
i3.print ();
i3 = i3;
i3.print ();
return 0;
}
lazy.cpp
#include <iostream>
using namespace std;
// 懶漢方式
class Singleton {
public:
static Singleton& getInst (void) {
if (! m_inst)
m_inst = new Singleton;
++m_cn;
return *m_inst;
}
void releaseInst (void) {
if (m_cn && --m_cn == 0)
delete this;
}
private:
Singleton (void) {
cout << "構造:" << this << endl;
}
Singleton (const Singleton&);
~Singleton (void) {
cout << "析構:" << this << endl;
m_inst = NULL;
}
static Singleton* m_inst;
static unsigned int m_cn;
};
Singleton* Singleton::m_inst = NULL;
unsigned int Singleton::m_cn = 0;
int main (void) {
Singleton& s1 = Singleton::getInst ();
Singleton& s2 = Singleton::getInst ();
Singleton& s3 = Singleton::getInst ();
cout << &s1 << ' ' << &s2 << ' ' << &s3 << endl;
s3.releaseInst ();
s2.releaseInst ();
s1.releaseInst ();
return 0;
}
memptr.cpp
#include <iostream>
#include <cstring>
using namespace std;
class Student {
public:
Student (const string& name, int age) :
m_name (name), m_age (age) {}
double m_weight;
string m_name;
int m_age;
void learn (const string& lesson) const {
cout << "我在學" << lesson << endl;
}
static void hello (void) {
cout << "你好!" << endl;
}
};
int main (void) {
string Student::*pname = &Student::m_name;
void* pv;
memcpy (&pv, &pname, 4);
cout << pv << endl;
int Student::*page = &Student::m_age;
memcpy (&pv, &page, 4);
cout << pv << endl;
Student s ("張飛", 25), *p = &s;
cout << s.*pname << endl;
cout << p->*page << endl;
Student s2 ("趙雲", 22);
cout << s2.*pname << endl;
void (Student::*plearn) (const string&) const =
&Student::learn;
(s.*plearn) ("C++");
(p->*plearn) ("UNIX");
void (*phello) (void) = Student::hello;
phello ();
return 0;
}
private.cpp
#include <iostream>
using namespace std;
class Nocopy {
public:
Nocopy (void) {}
private:
Nocopy (const Nocopy&);
Nocopy& operator= (const Nocopy&);
};
void foo (ostream os) {
os << "Hello, World !" << endl;
}
int main (void) {
Nocopy n1;
Nocopy n2 = n1;
Nocopy n3;
n3 = n1;
foo (cout);
- return 0;
}
static.cpp
#include <iostream>
using namespace std;
class A {
public:
static int m_i;
static void foo (void) {
cout << "foo:" << m_i << endl;
// m_d = 3.14;
// bar ();
}cd
double m_d;
void bar (void) {
m_i = 1000;
foo ();
}
};
int A::m_i = 1;
int main (void) {
A::m_i = 10;
A a1, a2;
cout << ++a1.m_i << endl;
cout << a2.m_i << endl;
A::foo ();
a1.foo ();
a1.bar ();
return 0;
}
string.cpp
拷貝構造: 如果一個類沒有定義拷貝建構函式,系統會提供一個預設拷貝建構函式。預設拷貝建構函式對於基本型別的成員變數,按位元組複製,對於類型別的成員變數,呼叫相應型別的拷貝建構函式。
#include <iostream>
#include <cstring>
::using namespace std;
class String {
public:
String (const char* str = NULL) {
m_str = new char[strlen(str?str:"")+1];
strcpy (m_str, str ? str : "");
}
~String (void) {
if (m_str) {
delete[] m_str;
m_str = NULL;
}
}
String (const String& that) :
m_str (strcpy (
new char[strlen(that.m_str)+1],
that.m_str)) {}
/* 菜鳥
void operator= (const String& that) {
m_str = new char[strlen(that.m_str)+1];
strcpy (m_str, that.m_str);
}*/
String& operator= (const String& that) {
if (&that != this) {
/* 小鳥
delete[] m_str;
m_str = new char[strlen(that.m_str)+1];
strcpy (m_str, that.m_str);
*/
/* 大鳥
char* str =
new char[strlen(that.m_str)+1];
delete[] m_str;
m_str = strcpy (str, that.m_str);
*/
// 老鳥
String temp (that);
swap (m_str, temp.m_str);
}
return *this;
}
const char* c_str (void) const {
return m_str;
}
private:
char* m_str;
};
int main (void) {
String s1 ("Hello, World !");
cout << s1.c_str () << endl;
String s2 = s1;
cout << s2.c_str () << endl;
String s3 ("Hello, Linux !");
try {
s1 = s3;
}
catch (exception& ex) {
cout << ex.what () << endl;
}
cout << s1.c_str () << endl;
return 0;
}
來自為知筆記(Wiz)