C++深入探究類與對(duì)象之友元與運(yùn)算符重載
友元
生活中你的家有客廳(Public),有你的臥室(Private),客廳所有來(lái)的客人都可以進(jìn)去,但是你的臥室是私有的,也就是說(shuō)只有你能進(jìn)去,但是呢,你也可以允許你的好閨蜜好基友進(jìn)去。
在程序里,有些私有屬性也想讓類外特殊的一些函數(shù)或者類進(jìn)行訪問(wèn),就需要用到友元的技術(shù)。
友元的目的就是讓一個(gè)函數(shù)或者類訪問(wèn)另一個(gè)類中私有成員。
友元的關(guān)鍵字為: friend
友元的三種實(shí)現(xiàn):
- 全局函數(shù)做友元
- 類做友元
- 成員函數(shù)做友元
1 全局函數(shù)做友元
class Building
{
//告訴編譯器 goodGay全局函數(shù) 是 Building類的好朋友,可以訪問(wèn)類中的私有內(nèi)容
friend void goodGay(Building * building);
public:
Building()
{
this->m_SittingRoom = "客廳";
this->m_BedRoom = "臥室";
}
public:
string m_SittingRoom; //客廳
private:
string m_BedRoom; //臥室
};
void goodGay(Building * building)
{
cout << "好基友正在訪問(wèn): " << building->m_SittingRoom << endl;
cout << "好基友正在訪問(wèn): " << building->m_BedRoom << endl;
}
void test01()
{
Building b;
goodGay(&b);
}
int main(){
test01();
system("pause");
return 0;
}2 類做友元
class Building;
class goodGay
{
public:
goodGay();
void visit();
private:
Building *building;
};
class Building
{
//告訴編譯器 goodGay類是Building類的好朋友,可以訪問(wèn)到Building類中私有內(nèi)容
friend class goodGay;
public:
Building();
public:
string m_SittingRoom; //客廳
private:
string m_BedRoom;//臥室
};
Building::Building()
{
this->m_SittingRoom = "客廳";
this->m_BedRoom = "臥室";
}
goodGay::goodGay()
{
building = new Building;
}
void goodGay::visit()
{
cout << "好基友正在訪問(wèn)" << building->m_SittingRoom << endl;
cout << "好基友正在訪問(wèn)" << building->m_BedRoom << endl;
}
void test01()
{
goodGay gg;
gg.visit();
}
int main(){
test01();
system("pause");
return 0;
}3 成員函數(shù)做友元
class Building;
class goodGay
{
public:
goodGay();
void visit(); //只讓visit函數(shù)作為Building的好朋友,可以發(fā)訪問(wèn)Building中私有內(nèi)容
void visit2();
private:
Building *building;
};
class Building
{
//告訴編譯器 goodGay類中的visit成員函數(shù) 是Building好朋友,可以訪問(wèn)私有內(nèi)容
friend void goodGay::visit();
public:
Building();
public:
string m_SittingRoom; //客廳
private:
string m_BedRoom;//臥室
};
Building::Building()
{
this->m_SittingRoom = "客廳";
this->m_BedRoom = "臥室";
}
goodGay::goodGay()
{
building = new Building;
}
void goodGay::visit()
{
cout << "好基友正在訪問(wèn)" << building->m_SittingRoom << endl;
cout << "好基友正在訪問(wèn)" << building->m_BedRoom << endl;
}
void goodGay::visit2()
{
cout << "好基友正在訪問(wèn)" << building->m_SittingRoom << endl;
//cout << "好基友正在訪問(wèn)" << building->m_BedRoom << endl;
}
void test01()
{
goodGay gg;
gg.visit();
}
int main(){
test01();
system("pause");
return 0;
}運(yùn)算符重載
運(yùn)算符重載概念:對(duì)已有的運(yùn)算符重新進(jìn)行定義,賦予其另一種功能,以適應(yīng)不同的數(shù)據(jù)類型
1 加號(hào)運(yùn)算符重載
作用:實(shí)現(xiàn)兩個(gè)自定義數(shù)據(jù)類型相加的運(yùn)算
class Person {
public:
Person() {};
Person(int a, int b)
{
this->m_A = a;
this->m_B = b;
}
//成員函數(shù)實(shí)現(xiàn) + 號(hào)運(yùn)算符重載
Person operator+(const Person& p) {
Person temp;
temp.m_A = this->m_A + p.m_A;
temp.m_B = this->m_B + p.m_B;
return temp;
}
public:
int m_A;
int m_B;
};
//全局函數(shù)實(shí)現(xiàn) + 號(hào)運(yùn)算符重載
//Person operator+(const Person& p1, const Person& p2) {
// Person temp(0, 0);
// temp.m_A = p1.m_A + p2.m_A;
// temp.m_B = p1.m_B + p2.m_B;
// return temp;
//}
//運(yùn)算符重載 可以發(fā)生函數(shù)重載
Person operator+(const Person& p2, int val)
{
Person temp;
temp.m_A = p2.m_A + val;
temp.m_B = p2.m_B + val;
return temp;
}
void test() {
Person p1(10, 10);
Person p2(20, 20);
//成員函數(shù)方式
Person p3 = p2 + p1; //相當(dāng)于 p2.operaor+(p1)
cout << "mA:" << p3.m_A << " mB:" << p3.m_B << endl;
Person p4 = p3 + 10; //相當(dāng)于 operator+(p3,10)
cout << "mA:" << p4.m_A << " mB:" << p4.m_B << endl;
}
int main() {
test();
system("pause");
return 0;
}總結(jié)1:對(duì)于內(nèi)置的數(shù)據(jù)類型的表達(dá)式的的運(yùn)算符是不可能改變的
總結(jié)2:不要濫用運(yùn)算符重載
2 左移運(yùn)算符重載
作用:可以輸出自定義數(shù)據(jù)類型
class Person {
friend ostream& operator<<(ostream& out, Person& p);
public:
Person(int a, int b)
{
this->m_A = a;
this->m_B = b;
}
//成員函數(shù) 實(shí)現(xiàn)不了 p << cout 不是我們想要的效果
//void operator<<(Person& p){
//}
private:
int m_A;
int m_B;
};
//全局函數(shù)實(shí)現(xiàn)左移重載
//ostream對(duì)象只能有一個(gè)
ostream& operator<<(ostream& out, Person& p) {
out << "a:" << p.m_A << " b:" << p.m_B;
return out;
}
void test() {
Person p1(10, 20);
cout << p1 << "hello world" << endl; //鏈?zhǔn)骄幊?
}
int main() {
test();
system("pause");
return 0;
}總結(jié):重載左移運(yùn)算符配合友元可以實(shí)現(xiàn)輸出自定義數(shù)據(jù)類型
3 遞增運(yùn)算符重載
作用: 通過(guò)重載遞增運(yùn)算符,實(shí)現(xiàn)自己的整型數(shù)據(jù)
class MyInteger {
friend ostream& operator<<(ostream& out, MyInteger myint);
public:
MyInteger() {
m_Num = 0;
}
//前置++
MyInteger& operator++() {
//先++
m_Num++;
//再返回
return *this;
}
//后置++
MyInteger operator++(int) {
//先返回
MyInteger temp = *this; //記錄當(dāng)前本身的值,然后讓本身的值加1,但是返回的是以前的值,達(dá)到先返回后++;
m_Num++;
return temp;
}
private:
int m_Num;
};
ostream& operator<<(ostream& out, MyInteger myint) {
out << myint.m_Num;
return out;
}
//前置++ 先++ 再返回
void test01() {
MyInteger myInt;
cout << ++myInt << endl;
cout << myInt << endl;
}
//后置++ 先返回 再++
void test02() {
MyInteger myInt;
cout << myInt++ << endl;
cout << myInt << endl;
}
int main() {
test01();
//test02();
system("pause");
return 0;
}總結(jié): 前置遞增返回引用,后置遞增返回值
4 賦值運(yùn)算符重載
c++編譯器至少給一個(gè)類添加4個(gè)函數(shù)
- 默認(rèn)構(gòu)造函數(shù)(無(wú)參,函數(shù)體為空)
- 默認(rèn)析構(gòu)函數(shù)(無(wú)參,函數(shù)體為空)
- 默認(rèn)拷貝構(gòu)造函數(shù),對(duì)屬性進(jìn)行值拷貝
- 賦值運(yùn)算符 operator=, 對(duì)屬性進(jìn)行值拷貝
如果類中有屬性指向堆區(qū),做賦值操作時(shí)也會(huì)出現(xiàn)深淺拷貝問(wèn)題
示例:
class Person
{
public:
Person(int age)
{
//將年齡數(shù)據(jù)開(kāi)辟到堆區(qū)
m_Age = new int(age);
}
//重載賦值運(yùn)算符
Person& operator=(Person &p)
{
if (m_Age != NULL)
{
delete m_Age;
m_Age = NULL;
}
//編譯器提供的代碼是淺拷貝
//m_Age = p.m_Age;
//提供深拷貝 解決淺拷貝的問(wèn)題
m_Age = new int(*p.m_Age);
//返回自身
return *this;
}
~Person()
{
if (m_Age != NULL)
{
delete m_Age;
m_Age = NULL;
}
}
//年齡的指針
int *m_Age;
};
void test01()
{
Person p1(18);
Person p2(20);
Person p3(30);
p3 = p2 = p1; //賦值操作
cout << "p1的年齡為:" << *p1.m_Age << endl;
cout << "p2的年齡為:" << *p2.m_Age << endl;
cout << "p3的年齡為:" << *p3.m_Age << endl;
}
int main() {
test01();
//int a = 10;
//int b = 20;
//int c = 30;
//c = b = a;
//cout << "a = " << a << endl;
//cout << "b = " << b << endl;
//cout << "c = " << c << endl;
system("pause");
return 0;
}5 關(guān)系運(yùn)算符重載
**作用:**重載關(guān)系運(yùn)算符,可以讓兩個(gè)自定義類型對(duì)象進(jìn)行對(duì)比操作
示例:
class Person
{
public:
Person(string name, int age)
{
this->m_Name = name;
this->m_Age = age;
};
bool operator==(Person & p)
{
if (this->m_Name == p.m_Name && this->m_Age == p.m_Age)
{
return true;
}
else
{
return false;
}
}
bool operator!=(Person & p)
{
if (this->m_Name == p.m_Name && this->m_Age == p.m_Age)
{
return false;
}
else
{
return true;
}
}
string m_Name;
int m_Age;
};
void test01()
{
//int a = 0;
//int b = 0;
Person a("孫悟空", 18);
Person b("孫悟空", 18);
if (a == b)
{
cout << "a和b相等" << endl;
}
else
{
cout << "a和b不相等" << endl;
}
if (a != b)
{
cout << "a和b不相等" << endl;
}
else
{
cout << "a和b相等" << endl;
}
}
int main() {
test01();
system("pause");
return 0;
}6 函數(shù)調(diào)用運(yùn)算符重載
- 函數(shù)調(diào)用運(yùn)算符 () 也可以重載
- 由于重載后使用的方式非常像函數(shù)的調(diào)用,因此稱為仿函數(shù)
- 仿函數(shù)沒(méi)有固定寫法,非常靈活
示例:
class MyPrint
{
public:
void operator()(string text)
{
cout << text << endl;
}
};
void test01()
{
//重載的()操作符 也稱為仿函數(shù)
MyPrint myFunc;
myFunc("hello world");
}
class MyAdd
{
public:
int operator()(int v1, int v2)
{
return v1 + v2;
}
};
void test02()
{
MyAdd add;
int ret = add(10, 10);
cout << "ret = " << ret << endl;
//匿名對(duì)象調(diào)用
cout << "MyAdd()(100,100) = " << MyAdd()(100, 100) << endl;
}
int main() {
test01();
test02();
system("pause");
return 0;
}到此這篇關(guān)于C++深入探究類與對(duì)象之友元與運(yùn)算符重載的文章就介紹到這了,更多相關(guān)C++友元內(nèi)容請(qǐng)搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關(guān)文章希望大家以后多多支持腳本之家!
相關(guān)文章
Qt使用QChart實(shí)現(xiàn)靜態(tài)顯示溫度變化曲線
QChart模塊是Qt?Charts庫(kù)的基礎(chǔ),提供了用于創(chuàng)建和顯示各種類型圖表的類和接口,本文主要介紹了如何使用QChart實(shí)現(xiàn)動(dòng)態(tài)顯示3個(gè)設(shè)備的溫度變化曲線,感興趣的可以了解一下2023-06-06
VisualStudio?禁用移動(dòng)文件到文件夾自動(dòng)修改命名空間功能
這篇文章主要介紹了VisualStudio?禁用移動(dòng)文件到文件夾自動(dòng)修改命名空間功能,文章底部給大家介紹了解決安裝VS2022時(shí),出現(xiàn)未能安裝包“Microsoft.VisualCpp.Redist.14,version=14.32.31332,chip”=x86,的問(wèn)題及解決方法,需要的朋友可以參考下2022-09-09
淺析string 與char* char[]之間的轉(zhuǎn)換
與char*不同的是,string不一定以NULL('\0')結(jié)束。string長(zhǎng)度可以根據(jù)length()得到,string可以根據(jù)下標(biāo)訪問(wèn)。所以,不能將string直接賦值給char*2013-10-10
C語(yǔ)言運(yùn)算符及其優(yōu)先級(jí)匯總表口訣
由于C語(yǔ)言的運(yùn)算符優(yōu)先級(jí)與C++的不完全一樣(主要是增加了幾個(gè)運(yùn)算符),所以這個(gè)口訣不能完全實(shí)用于C++.但是應(yīng)該能夠兼容,大家可以比較一下他們的區(qū)別應(yīng)該就能夠很快掌握C++的優(yōu)先級(jí)的2013-07-07
C語(yǔ)言實(shí)現(xiàn)學(xué)生打卡系統(tǒng)
這篇文章主要為大家詳細(xì)介紹了C語(yǔ)言實(shí)現(xiàn)學(xué)生打卡系統(tǒng),文中示例代碼介紹的非常詳細(xì),具有一定的參考價(jià)值,感興趣的小伙伴們可以參考一下2020-12-12
C語(yǔ)言進(jìn)階幾分鐘帶你理解大小端存儲(chǔ)模式
這篇文章主要為大家介紹了C語(yǔ)言進(jìn)階大小端模式的示例詳解,帶各位讀者朋友五分鐘腳踩大小端模式,有需要的朋友可以借鑒參考下,希望能夠有所幫助2022-02-02

