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
#include<iostream>usingnamespace std;classComplex{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:支持常量型左操作数constComplexoperator+(constComplex& r)const{returnComplex(m_r + r.m_r, m_i + r.m_i);}private:0int m_r;int m_i;friendconstComplexoperator-(constComplex&,constComplex&);};constComplexoperator-(constComplex& l,constComplex& r){returnComplex(l.m_r - r.m_r, l.m_i - r.m_i);}int main (void){constComplex c1 (1,2);c1.print ();constComplex 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+2ireturn0;}
hungry.cpp
#include<iostream>usingnamespace std;// 饿汉方式classSingleton{public:staticSingleton& getInst (void){return s_inst;}private:Singleton(void){}Singleton(constSingleton&);staticSingleton s_inst;};SingletonSingleton::s_inst;int main (void){Singleton& s1 =Singleton::getInst ();Singleton& s2 =Singleton::getInst ();Singleton& s3 =Singleton::getInst ();cout <<&s1 <<' '<<&s2 <<' '<<&s3 << endl;return0;}
integer.cpp
#include<iostream>usingnamespace std;classInteger{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 ());return0;}
integer2.cpp
#include<iostream>usingnamespace std;classInteger{public:Integer(int data): m_data (newint(data)){}~Integer(void){if(m_data){delete m_data;m_data = NULL;}}void print (void)const{cout <<*m_data << endl;}Integer(constInteger& that):m_data (newint(*that.m_data)){}voidset(int data){*m_data = data;}Integer&operator=(constInteger& that){// 防止自赋值if(&that !=this){// 释放旧资源delete m_data;// 分配新资源m_data =newint(*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 ();// 30i3 = i1;// 拷贝赋值// i3.operator= (i1);i3.print ();// 10i3.set(40);i3.print ();// 40i1.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 ();return0;}
lazy.cpp
#include<iostream>usingnamespace std;// 懒汉方式classSingleton{public:staticSingleton& getInst (void){if(! m_inst)m_inst =newSingleton;++m_cn;return*m_inst;}void releaseInst (void){if(m_cn &&--m_cn ==0)deletethis;}private:Singleton(void){cout <<"构造:"<<this<< endl;}Singleton(constSingleton&);~Singleton(void){cout <<"析构:"<<this<< endl;m_inst = NULL;}staticSingleton* m_inst;staticunsignedint m_cn;};Singleton*Singleton::m_inst = NULL;unsignedintSingleton::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 ();return0;}

memptr.cpp
#include<iostream>#include<cstring>usingnamespace std;classStudent{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;}staticvoid hello (void){cout <<"你好!"<< endl;}};int main (void){string Student::*pname =&Student::m_name;void* pv;memcpy (&pv,&pname,4);cout << pv << endl;intStudent::*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 ();return0;}
private.cpp
#include<iostream>usingnamespace std;classNocopy{public:Nocopy(void){}private:Nocopy(constNocopy&);Nocopy&operator=(constNocopy&);};void foo (ostream os){os <<"Hello, World !"<< endl;}int main (void){Nocopy n1;Nocopy n2 = n1;Nocopy n3;n3 = n1;foo (cout);- return0;
}
static.cpp
#include<iostream>usingnamespace std;class A {public:staticint m_i;staticvoid foo (void){cout <<"foo:"<< m_i << endl;// m_d = 3.14;// bar ();}cddouble 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 ();return0;}
string.cpp
#include<iostream>#include<cstring>::usingnamespace std;classString{public:String(constchar* str = NULL){m_str =newchar[strlen(str?str:"")+1];strcpy (m_str, str ? str :"");}~String(void){if(m_str){delete[] m_str;m_str = NULL;}}String(constString& that):m_str (strcpy (newchar[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=(constString& 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;}constchar* 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;return0;}
如果一个类没有定义拷贝构造函数,系统会提供一个缺省拷贝构造函数。缺省拷贝构造函数对于基本类型的成员变量,按字节复制,对于类类型的成员变量,调用相应类型的拷贝构造函数。
<wiz_tmp_tag id="wiz-table-range-border" contenteditable="false" style="display: none;">





浙公网安备 33010602011771号