4.5.3遞增運(yùn)算符重載
作用:通過(guò)重載遞增運(yùn)算符,實(shí)現(xiàn)自己的整形數(shù)據(jù)
1.前置++
2.后置++(重載時(shí)引入占位參數(shù)int,用以告知編輯器為后置遞增)
總結(jié):前置遞增返回引用,后置遞增返回值
示例:
//自定義整型
class MyInteger
{
friend ostream &operator <<(ostream &os, MyInteger myint);
public:
MyInteger()
{
m_Num = 0;
}
//重載前置++運(yùn)算符
//返回引用是為了一直對(duì)一個(gè)數(shù)據(jù)進(jìn)行遞增操作
MyInteger& operator++()
{
++m_Num;
return *this;
}
//重載后置++運(yùn)算符
//int代表占位參數(shù),用于區(qū)分前置和后置遞增
//一定要返回值,因?yàn)榉祷鼐植繉?duì)象的引用是非法操作
//先返回,后++
MyInteger operator++(int )
{
MyInteger temp = *this;//記錄當(dāng)前本身的值
++m_Num;
return temp;
}
private:
int m_Num;
};
ostream &operator <<(ostream &os, MyInteger myint)
{
os << myint.m_Num;
return os;
}
void test01()
{
MyInteger myint;
cout <<++myint << endl;
cout << myint << endl;
}
void test02()
{
MyInteger myint;
cout << myint++ << endl;
cout << myint << endl;
}
4.5.4賦值運(yùn)算符重載
C++至少給一個(gè)類(lèi)添加4個(gè)函數(shù):
1.默認(rèn)構(gòu)造函數(shù)(無(wú)參,函數(shù)體為空)
2.默認(rèn)析構(gòu)函數(shù)(無(wú)參,函數(shù)體為空)
3.默認(rèn)拷貝構(gòu)造函數(shù),對(duì)屬性進(jìn)行值拷貝;
4.賦值運(yùn)算符operator=,對(duì)屬性進(jìn)行值拷貝
如果類(lèi)中有屬性指向堆區(qū),做賦值操作時(shí)也會(huì)出現(xiàn)深淺拷貝問(wèn)題;
淺拷貝:堆區(qū)內(nèi)存重復(fù)釋放,程序崩潰;
解決方案:利用深拷貝,解決淺拷貝帶來(lái)的問(wèn)題;
示例:
class Person
{
public:
Person(int age)
{
m_Age = new int(age);
cout << "Person(int)" << endl;
}
//注意:返回的是引用,才能返回對(duì)象自身
Person& operator=(const Person &p)
{
//m_Age = p.m_Age;//編譯器提供的淺拷貝
//應(yīng)該先判斷是否有屬性在堆區(qū),如果有,先釋放干凈
if (m_Age != NULL)
{
delete m_Age;
m_Age = NULL;
}
//然后再深拷貝
m_Age = new int(*p.m_Age);
return *this;
}
~Person()
{
if (m_Age != NULL)
{
delete m_Age;
m_Age = NULL;
}
cout << "~Person()" << endl;
}
//private:
int *m_Age;
};
4.5.5關(guān)系運(yùn)算符重載
1.推薦:友元函數(shù)的形式重載
2.也可成員函數(shù)形式重載
4.5.6函數(shù)調(diào)用運(yùn)算符重載
1.函數(shù)調(diào)用運(yùn)算符()也可以重載;
2.由于重載后使用方式非常像函數(shù)調(diào)用,因此稱(chēng)為仿函數(shù);
3.仿函數(shù)沒(méi)有固定寫(xiě)法,非常靈活;
補(bǔ)充:不想創(chuàng)建一個(gè)對(duì)象時(shí),可使用匿名函數(shù)對(duì)象;
示例:
//打印輸出類(lèi)
class MyPrint
{
public:
void operator()(string test)
{
cout << test << endl;
}
};
//仿函數(shù)非常靈活,沒(méi)有固定寫(xiě)法
class MyAdd
{
public:
int operator()(int a, int b)
{
return a + b;
}
};
void test01()
{
MyPrint myp;
myp("lalalala");//由于使用起來(lái)非常類(lèi)似于函數(shù)調(diào)用,因此稱(chēng)為仿函數(shù)
}
void test02()
{
MyAdd myadd;
cout<<myadd(5, 9)<<endl;
//匿名函數(shù)對(duì)象
cout << MyAdd()(10, 10) << endl;
}
4.6繼承
4.6.1繼承基本語(yǔ)法
繼承時(shí)面向?qū)ο笕筇匦灾唬?/p>
利用繼承技術(shù),可以減少重復(fù)代碼;
語(yǔ)法:class 子類(lèi)(派生類(lèi)) : 繼承方式? 父類(lèi)(基類(lèi))
4.6.2繼承方式
共三種:
1.公共繼承
2.保護(hù)繼承
3.私有繼承

4.6.3繼承中的對(duì)象模型
如何使用工具查看vs中的對(duì)象模型:
利用開(kāi)發(fā)人員命令提示工具查看對(duì)象模型
1.跳轉(zhuǎn)盤(pán)符? D:
2.跳轉(zhuǎn)文件路徑 cd ..具體路徑下
3.查看命令
cl /d1 reportSingleClassLayout 類(lèi)名 文件名(.cpp)
示例:
class Base
{
public:
int m_A;
protected:
int m_B;
private:
int m_C;
};
class Son
:public Base
{
public:
int m_D;
};
void test01()
{
//父類(lèi)中所有非靜態(tài)成員屬性都會(huì)被子類(lèi)繼承下去
//父類(lèi)中私有成員屬性 是被編譯器隱藏了
//因此是訪問(wèn)不到,但是確實(shí)被繼承下去了
cout << "sizeof(Son)=" << sizeof(Son) << endl;
}
注意:父類(lèi)中的私有成員也被子類(lèi)繼承了,只是訪問(wèn)不到
4.6.4繼承中的構(gòu)造和析構(gòu)順序
先調(diào)用父類(lèi)構(gòu)造函數(shù),再調(diào)用子類(lèi)構(gòu)造函數(shù);
析構(gòu)順序與構(gòu)造相反;
4.6.5繼承同名成員處理方式
1.訪問(wèn)子類(lèi)同名成員,直接訪問(wèn)即可;
2.訪問(wèn)父類(lèi)同名成員,需要加作用域;
示例:
class Base
{
public:
void func()
{
cout << "Base::func()" << endl;
}
void func(int a)
{
cout << "Base::func(int)" << endl;
}
};
class Son
:public Base
{
public:
void func()
{
cout << "Son::func()" << endl;
}
};
void test03()
{
Son s;
//如果子類(lèi)中出現(xiàn)和父類(lèi)同名的成員函數(shù)
//子類(lèi)的同名成員會(huì)隱藏掉父類(lèi)中所有同名成員函數(shù)
//“所有”是指只要函數(shù)名相同,哪怕參數(shù)不同
//如果想訪問(wèn)到父類(lèi)中被隱藏的同名成員函數(shù),需要加作用域
//s.func(100);//error
s.Base::func(100);
}
總結(jié):
1.子類(lèi)對(duì)象可以直接訪問(wèn)到子類(lèi)中的同名成員;
2.子類(lèi)對(duì)象加作用域可以訪問(wèn)到父類(lèi)同名成員;
3.當(dāng)父類(lèi)和子類(lèi)擁有同名的成員函數(shù),子類(lèi)會(huì)隱藏父類(lèi)中同名成員函數(shù),加作用域可以訪問(wèn)到父類(lèi)中的同名成員函數(shù);
4.6.6繼承同名靜態(tài)成員處理方式
靜態(tài)成員和非靜態(tài)成員出現(xiàn)同名,處理方式一致;
1.訪問(wèn)子類(lèi)同名成員,直接訪問(wèn)即可;
2.訪問(wèn)父類(lèi)同名成員,需要加作用域;
注意:靜態(tài)成員可以通過(guò)類(lèi)名訪問(wèn);
示例:
void test01()
? {
? //1.通過(guò)對(duì)象訪問(wèn)
? /*Son s;
? cout << "Base::m_A=" << s.Base::m_A << endl;
? cout << "Son::m_A=" << s.m_A << endl;*/
? //2.通過(guò)類(lèi)名訪問(wèn)
? cout << "Base::m_A=" << Base::m_A << endl;
? cout << "Son::m_A=" << Son::m_A << endl;
? //第一個(gè)::代表通過(guò)類(lèi)名方式訪問(wèn)?
? //第二個(gè)::代表訪問(wèn)父類(lèi)作用域下
? cout << "Base::m_A=" << Son::Base::m_A << endl;
? }
? void test02()
? {
? //1.通過(guò)對(duì)象訪問(wèn)
? Son s;
? s.func();
? s.Base::func();
? //2.通過(guò)類(lèi)名訪問(wèn)
? Son::func();
? Son::Base::func();
? }