友元函数的正确用法和滥用方法

2024-05-31 04:58

本文主要是介绍友元函数的正确用法和滥用方法,希望对大家解决编程问题提供一定的参考价值,需要的开发者们随着小编来一起学习吧!

  1. 重点:友元函数用于左移(<<)和右移(>>)运算符的重载, 而其他的运算符都要写成成员函数,最好不要滥用友元函数。

  2. 第一种情况:所有函数写在类的内部
  3. 代码如下:
  4. #include "stdafx.h"
    #include "iostream"
    using namespace std;template <typename T>
    class Complex
    {<span style="color:#ff0000;">friend Complex operator-(const Complex &c1, const Complex &c2)//这种情况下就属于滥用友元函数{Complex tmp(c1.a - c2.a, c1.b - c2.b);return tmp;}</span>//重载<<<span style="color:#009900;">friend ostream& operator<<(ostream &out, const Complex &obj);{out << obj.a << "+" <<obj.b << "i" << endl;return out;}</span>public:Complex(T a, T b){this->a = a;this->b = b;}Complex operator+(const Complex &obj){Complex tmp(a+obj.a, b+obj.b);return tmp;}
    private:T a;T b;
    };int _tmain(int argc, _TCHAR* argv[])
    {Complex<int> c1(1, 2), c2(3, 4);Complex<int> c3 = c1 + c2;cout << c3;//滥用友元函数{Complex<int> c4 = c1 - c2;cout <<"c4 = "<< c4;}printf("Hello...\n");system("pause");return 0;
    }


  5. 第二种情况:所有函数在类的外部,但在一个CPP里面
  6. 代码如下:
  7. <pre name="code" class="cpp">#include "stdafx.h"
    #include "iostream"
    using namespace std;//一下这部分就是为了解决operator-友元函数问题所要加的部分
    <span style="color:#ff0000;">template <typename T>
    class Complex;
    template <typename T>
    Complex<T> operator-(const Complex<T> &c1, const Complex<T> &c2);</span>template <typename T>
    class Complex
    {<span style="color:#ff0000;">friend Complex<T> operator-<T>(const Complex<T> &c1, const Complex<T> &c2);//这里多加了很多<T></span>//重载<<<span style="color:#006600;background-color: rgb(255, 255, 255);">friend ostream& operator<< <T> (ostream &out, const Complex &obj);//这里比在内部的时候多加了<T></span>public:Complex(T a, T b);Complex operator+(const Complex &obj);
    private:T a;T b;
    };//滥用 友元函数
    <span style="color:#ff0000;">template <typename T>
    Complex<T> operator-(const Complex<T> &c1, const Complex<T> &c2)
    {Complex<T> tmp(c1.a - c2.a, c1.b - c2.b);return tmp;
    }</span><span style="color:#006600;">template <typename T>
    ostream& operator<<(ostream &out, const Complex<T> &obj)//由于友元函数不是类的成员函数,是全局函数,所以无需域作用符
    {out << obj.a << "+" << obj.b << "i" << endl;return out;
    }</span>//构造函数的实现 写在了类的外部
    template <typename T>
    Complex<T>::Complex(T a, T b)
    {this->a = a;this->b = b;
    }//本质是 : 模板是两次 编译生成的第一次生成的函数头和第二次生成的函数头不一样
    //成员函数 实现 +运算符重载
    template <typename T>
    Complex<T> Complex<T>::operator+(const Complex<T> &obj)
    {Complex tmp(a + obj.a, b + obj.b);return tmp;
    }int _tmain(int argc, _TCHAR* argv[])
    {//需要把模板类 进行具体化以后  才能定义对象  C++编译器要分配内存Complex<int> c1(1, 2), c2(3, 4);Complex<int> c3 = c1 + c2;cout << c3;//滥用友元函数{Complex<int> c4 = c1 - c2;cout << "c4 = " << c4;}printf("Hello...\n");system("pause");return 0;
    }

    问题如下:大家可以比较仔细比较一下这两段代码,当友元函数在类外部实现的时候是很繁琐的,一般不建议用,这里只是提供一种解决方法,即使是第三种情形:所有函数写在类的内部(分别在.h和.cpp),滥用情况也可以解决,方法与第二种类似!
     

这篇关于友元函数的正确用法和滥用方法的文章就介绍到这儿,希望我们推荐的文章对编程师们有所帮助!



http://www.chinasem.cn/article/1017408

相关文章

Java 字符数组转字符串的常用方法

《Java字符数组转字符串的常用方法》文章总结了在Java中将字符数组转换为字符串的几种常用方法,包括使用String构造函数、String.valueOf()方法、StringBuilder以及A... 目录1. 使用String构造函数1.1 基本转换方法1.2 注意事项2. 使用String.valu

Python中使用defaultdict和Counter的方法

《Python中使用defaultdict和Counter的方法》本文深入探讨了Python中的两个强大工具——defaultdict和Counter,并详细介绍了它们的工作原理、应用场景以及在实际编... 目录引言defaultdict的深入应用什么是defaultdictdefaultdict的工作原理

使用Python进行文件读写操作的基本方法

《使用Python进行文件读写操作的基本方法》今天的内容来介绍Python中进行文件读写操作的方法,这在学习Python时是必不可少的技术点,希望可以帮助到正在学习python的小伙伴,以下是Pyth... 目录一、文件读取:二、文件写入:三、文件追加:四、文件读写的二进制模式:五、使用 json 模块读写

Oracle数据库使用 listagg去重删除重复数据的方法汇总

《Oracle数据库使用listagg去重删除重复数据的方法汇总》文章介绍了在Oracle数据库中使用LISTAGG和XMLAGG函数进行字符串聚合并去重的方法,包括去重聚合、使用XML解析和CLO... 目录案例表第一种:使用wm_concat() + distinct去重聚合第二种:使用listagg,

Java后端接口中提取请求头中的Cookie和Token的方法

《Java后端接口中提取请求头中的Cookie和Token的方法》在现代Web开发中,HTTP请求头(Header)是客户端与服务器之间传递信息的重要方式之一,本文将详细介绍如何在Java后端(以Sp... 目录引言1. 背景1.1 什么是 HTTP 请求头?1.2 为什么需要提取请求头?2. 使用 Spr

Java如何通过反射机制获取数据类对象的属性及方法

《Java如何通过反射机制获取数据类对象的属性及方法》文章介绍了如何使用Java反射机制获取类对象的所有属性及其对应的get、set方法,以及如何通过反射机制实现类对象的实例化,感兴趣的朋友跟随小编一... 目录一、通过反射机制获取类对象的所有属性以及相应的get、set方法1.遍历类对象的所有属性2.获取

Java中的Opencv简介与开发环境部署方法

《Java中的Opencv简介与开发环境部署方法》OpenCV是一个开源的计算机视觉和图像处理库,提供了丰富的图像处理算法和工具,它支持多种图像处理和计算机视觉算法,可以用于物体识别与跟踪、图像分割与... 目录1.Opencv简介Opencv的应用2.Java使用OpenCV进行图像操作opencv安装j

Ubuntu系统怎么安装Warp? 新一代AI 终端神器安装使用方法

《Ubuntu系统怎么安装Warp?新一代AI终端神器安装使用方法》Warp是一款使用Rust开发的现代化AI终端工具,该怎么再Ubuntu系统中安装使用呢?下面我们就来看看详细教程... Warp Terminal 是一款使用 Rust 开发的现代化「AI 终端」工具。最初它只支持 MACOS,但在 20

Python实现数据清洗的18种方法

《Python实现数据清洗的18种方法》本文主要介绍了Python实现数据清洗的18种方法,文中通过示例代码介绍的非常详细,对大家的学习或者工作具有一定的参考学习价值,需要的朋友们下面随着小编来一起学... 目录1. 去除字符串两边空格2. 转换数据类型3. 大小写转换4. 移除列表中的重复元素5. 快速统

Debian如何查看系统版本? 7种轻松查看Debian版本信息的实用方法

《Debian如何查看系统版本?7种轻松查看Debian版本信息的实用方法》Debian是一个广泛使用的Linux发行版,用户有时需要查看其版本信息以进行系统管理、故障排除或兼容性检查,在Debia... 作为最受欢迎的 linux 发行版之一,Debian 的版本信息在日常使用和系统维护中起着至关重要的作