千家信息网

C++友元与运算符重载怎么应用

发表于:2025-01-19 作者:千家信息网编辑
千家信息网最后更新 2025年01月19日,这篇文章主要讲解了"C++友元与运算符重载怎么应用",文中的讲解内容简单清晰,易于学习与理解,下面请大家跟着小编的思路慢慢深入,一起来研究和学习"C++友元与运算符重载怎么应用"吧!友元生活中你的家有
千家信息网最后更新 2025年01月19日C++友元与运算符重载怎么应用

这篇文章主要讲解了"C++友元与运算符重载怎么应用",文中的讲解内容简单清晰,易于学习与理解,下面请大家跟着小编的思路慢慢深入,一起来研究和学习"C++友元与运算符重载怎么应用"吧!

友元

生活中你的家有客厅(Public),有你的卧室(Private),客厅所有来的客人都可以进去,但是你的卧室是私有的,也就是说只有你能进去,但是呢,你也可以允许你的好闺蜜好基友进去。

在程序里,有些私有属性也想让类外特殊的一些函数或者类进行访问,就需要用到友元的技术。

友元的目的就是让一个函数或者类访问另一个类中私有成员。

友元的关键字为: friend

友元的三种实现:

  • 全局函数做友元

  • 类做友元

  • 成员函数做友元

1 全局函数做友元

class Building{        //告诉编译器 goodGay全局函数 是 Building类的好朋友,可以访问类中的私有内容        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 << "好基友正在访问: " << building->m_SittingRoom << endl;        cout << "好基友正在访问: " << 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类的好朋友,可以访问到Building类中私有内容        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 << "好基友正在访问" << building->m_SittingRoom << endl;        cout << "好基友正在访问" << building->m_BedRoom << endl;}void test01(){        goodGay gg;        gg.visit();}int main(){        test01();        system("pause");        return 0;}

3 成员函数做友元

class Building;class goodGay{public:        goodGay();        void visit(); //只让visit函数作为Building的好朋友,可以发访问Building中私有内容        void visit2(); private:        Building *building;};class Building{        //告诉编译器  goodGay类中的visit成员函数 是Building好朋友,可以访问私有内容        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 << "好基友正在访问" << building->m_SittingRoom << endl;        cout << "好基友正在访问" << building->m_BedRoom << endl;}void goodGay::visit2(){        cout << "好基友正在访问" << building->m_SittingRoom << endl;        //cout << "好基友正在访问" << building->m_BedRoom << endl;}void test01(){        goodGay  gg;        gg.visit();}int main(){        test01();        system("pause");        return 0;}

运算符重载

运算符重载概念:对已有的运算符重新进行定义,赋予其另一种功能,以适应不同的数据类型

1 加号运算符重载

作用:实现两个自定义数据类型相加的运算

class Person {public:        Person() {};        Person(int a, int b)        {                this->m_A = a;                this->m_B = b;        }        //成员函数实现 + 号运算符重载        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;};//全局函数实现 + 号运算符重载//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;//}//运算符重载 可以发生函数重载 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);        //成员函数方式        Person p3 = p2 + p1;  //相当于 p2.operaor+(p1)        cout << "mA:" << p3.m_A << " mB:" << p3.m_B << endl;        Person p4 = p3 + 10; //相当于 operator+(p3,10)        cout << "mA:" << p4.m_A << " mB:" << p4.m_B << endl;}int main() {        test();        system("pause");        return 0;}

总结1:对于内置的数据类型的表达式的的运算符是不可能改变的

总结2:不要滥用运算符重载

2 左移运算符重载

作用:可以输出自定义数据类型

class Person {        friend ostream& operator<<(ostream& out, Person& p);public:        Person(int a, int b)        {                this->m_A = a;                this->m_B = b;        }        //成员函数 实现不了  p << cout 不是我们想要的效果        //void operator<<(Person& p){        //}private:        int m_A;        int m_B;};//全局函数实现左移重载//ostream对象只能有一个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; //链式编程}int main() {        test();        system("pause");        return 0;}

总结:重载左移运算符配合友元可以实现输出自定义数据类型

3 递增运算符重载

作用: 通过重载递增运算符,实现自己的整型数据

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; //记录当前本身的值,然后让本身的值加1,但是返回的是以前的值,达到先返回后++;                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;}

总结: 前置递增返回引用,后置递增返回值

4 赋值运算符重载

c++编译器至少给一个类添加4个函数

  • 默认构造函数(无参,函数体为空)

  • 默认析构函数(无参,函数体为空)

  • 默认拷贝构造函数,对属性进行值拷贝

  • 赋值运算符 operator=, 对属性进行值拷贝

如果类中有属性指向堆区,做赋值操作时也会出现深浅拷贝问题

示例:

class Person{public:        Person(int age)        {                //将年龄数据开辟到堆区                m_Age = new int(age);        }        //重载赋值运算符         Person& operator=(Person &p)        {                if (m_Age != NULL)                {                        delete m_Age;                        m_Age = NULL;                }                //编译器提供的代码是浅拷贝                //m_Age = p.m_Age;                //提供深拷贝 解决浅拷贝的问题                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 关系运算符重载

**作用:**重载关系运算符,可以让两个自定义类型对象进行对比操作

示例:

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 函数调用运算符重载

  • 函数调用运算符 () 也可以重载

  • 由于重载后使用的方式非常像函数的调用,因此称为仿函数

  • 仿函数没有固定写法,非常灵活

示例:

class MyPrint{public:        void operator()(string text)        {                cout << text << endl;        }};void test01(){        //重载的()操作符 也称为仿函数        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;        //匿名对象调用          cout << "MyAdd()(100,100) = " << MyAdd()(100, 100) << endl;}int main() {        test01();        test02();        system("pause");        return 0;}

感谢各位的阅读,以上就是"C++友元与运算符重载怎么应用"的内容了,经过本文的学习后,相信大家对C++友元与运算符重载怎么应用这一问题有了更深刻的体会,具体使用情况还需要大家实践验证。这里是,小编将为大家推送更多相关知识点的文章,欢迎关注!

0