C++成员函数与非成员函数实现运算符重载

2023-10-27

目录

1.成员函数运算符重载

2.非成员函数【友元函数】运算符重载

3.运算符重载的禁区与规则

成员函数与非成员函数重载区别

区别:

两种方式选择:

特殊情况

4.运算符重载的禁区和规则


1.成员函数运算符重载

        需求:
        // 规则:

        // 一斤牛肉:2斤猪肉

        // 一斤羊肉:3斤猪肉

Cow.h

#pragma once


class Pork;
class Goat;

class Cow{
public:
	Cow(int weight=0);
	Pork operator+(const Goat&goat);
	Pork operator+(const Cow& cow);
private:
	int weight;
};

 Cow.cpp

#include "Cow.h"
#include"Goat.h"
#include"Pork.h"

Cow::Cow(int weight) {
	this->weight = weight;
}

Pork Cow::operator+(const Goat& goat) {
	int temp = this->weight*2 + goat.GetWeight() * 3;
	return Pork(temp);
}

Pork Cow::operator+(const Cow& cow) {
	int temp = (this->weight + cow.weight) * 2;
	return Pork(temp);
}

 Goat.h

#pragma once
class Goat
{
public:
	Goat(int weight = 0);
	int GetWeight ()const;
private:
	int weight;
};

 Goat.cpp

#include "Goat.h"

Goat::Goat(int weight) {
	this->weight = weight;
}

int Goat::GetWeight() const {
	return weight;
}

 Pork.h

#pragma once
#include<string>

class Pork
{
public:
	Pork(int weight = 0);
	std::string descriWeight();
private:
	int weight;

};

 Pork.cpp

#include "Pork.h"
#include<sstream>

Pork::Pork(int weight) {
	this->weight = weight;
}

std::string Pork::descriWeight() {
	std::stringstream ret;
	ret << this->weight << "斤猪肉";
	return ret.str();
}

 main.cpp

#include"Cow.h"
#include"Goat.h"
#include"Pork.h"
#include<iostream>

int main() {
	Cow cow1(2000);
	Cow cow2(1800);
	Goat goat(1000);
	Pork pork1 = cow1 + goat;
	Pork pork2 = cow1 + cow2;
	std::cout << "一只牛+一只羊为:\t";
	std::cout << pork1.descriWeight() << std::endl;

	std::cout << "两只牛为:\t";
	std::cout << pork2.descriWeight() << std::endl;
	system("pause");
	return 0;
}

 运行结果:

 

2.非成员函数【友元函数】运算符重载

Cow.h

#pragma once


class Pork;
class Goat;

class Cow{
public:
	Cow(int weight=0);
	friend Pork operator+(const Cow & cow ,const Goat&goat);
	friend Pork operator+(const Cow& cow1, const Cow& cow2);
private:
	int weight;
};

 Goat.h

#pragma once

class Cow;
class Pork;
class Goat{
public:
	Goat(int weight = 0);
	friend Pork operator+(const Cow& cow, const Goat& goat);
private:
	int weight;
};

 main.cpp

#include"Cow.h"
#include"Goat.h"
#include"Pork.h"
#include<iostream>

Pork operator+(const Cow& cow, const Goat& goat) {
	int temp = cow.weight * 2 + goat.weight * 3;
	return Pork(temp);
}

Pork operator+(const Cow& cow1, const Cow& cow2) {
	int temp = cow1.weight * 2 + cow2.weight * 2;
	return Pork(temp);
}

int main() {
	Cow cow1(2000);
	Cow cow2(1800);
	Goat goat(1000);
	Pork pork1 = cow1 + goat;
	//当写 p=g+c,编译器会先找g.operator如果找不到,则寻找operator(g1,c1),如果两个都找到,编译   
	//器会不知道调用哪个(不能同时使用两种方式重载,会出现二义性)
	Pork pork2 = cow1 + cow2;
	std::cout << "一只牛+一只羊为:\t";
	std::cout << pork1.descriWeight() << std::endl;

	std::cout << "两只牛为:\t";
	std::cout << pork2.descriWeight() << std::endl;
	system("pause");
	return 0;
}

运行结果:

 

3.运算符重载的禁区与规则

成员函数与非成员函数重载区别

区别:

使用成员函数来实现运算符重载时,少写一个参数,因为第一个参数就是this指针

两种方式选择:

1.一般情况下,单目运算符(运算只需一个参数/对象),使用成员函数进行重载更方便

2.一般情况,双木运算符重载,使用友元函数更直观

        方便实现a+b和b+a的相同效果,成员函数方式无法实现

        例如 cow +100 :=cow.operator(100) 友元函数和成员函数都能实现

                而100+cow  只能用友元函数实现

        "+"法运算符重载只能有两个参数,成员函数重载时已经默认一个参数为this

特殊情况

(1) =  ()  [ ]  ->  不能重载为类的友元函数!!(否则可能和 C++的其他规则矛盾)只能使用成员函数形式进行重载

(2)如果运算符的第一个操作数要求使用隐式类型转换,则必须为友元函数(成员函数方式的第一个参数为this指针)

4.运算符重载的禁区和规则

1. 为了防止对标准类型进行运算符重载,
    C++规定重载运算符的操作对象至少有一个不是标准类型,而是用户自定义的类型

   比如不能重载 1+2

   但是可以重载  cow + 2 和 2 + cow   // cow是自定义的对象

2.不能改变原运算符的语法规则, 比如不能把双目运算符重载为单目运算

3.不能改变原运算符的优先级

4.不能创建新的运算符,比如 operator**就是非法的, operator*是可以的

5.不能对以下这四种运算符,使用友元函数进行重载

   = 赋值运算符,()函数调用运算符,[ ]下标运算符,->通过指针访问类成员

6. 不能对禁止重载的运算符进行重载

不能被重载的运算符

成员访问

.

域运算

::

内存长度运算

sizeof

三目运算

 ? : :

预处理

#

可以被重载的运算符

双目运算符

+    -    *    /    %

关系运算符

==  !=   <   <=   >   >=

逻辑运算符

&&  ||    !

单目运算符

+(正号)   -(负号)  *(指针)  &(取地址)  ++   --

位运算

&    |   ~    ^    <<(左移)    >>(右移)

赋值运算符

=   +=   -=    *=   /=   %=  &=  |=  ^=  <<=   >>=

内存分配

new   delete  new[ ]   delete[ ]

其他

( )  函数调用

-> 成员访问
[ ]   下标

,  逗号

 

本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

C++成员函数与非成员函数实现运算符重载 的相关文章

  • 如何使用 C# 中的参数将用户重定向到 paypal

    如果我有像下面这样的简单表格 我可以用它来将用户重定向到 PayPal 以完成付款
  • C 编程 - 文件 - fwrite

    我有一个关于编程和文件的问题 while current NULL if current gt Id Doctor 0 current current gt next id doc current gt Id Doctor if curre
  • “构建”构建我的项目,“构建解决方案”则不构建

    我刚刚开始使用VS2010 我有一个较大的解决方案 已从 VS2008 成功迁移 我已将一个名为 Test 的控制台应用程序项目添加到解决方案中 选择构建 gt 构建解决方案不编译新项目 选择构建 gt 构建测试确实构建了项目 在失败的情况
  • 以文化中立的方式将字符串拆分为单词

    我提出了下面的方法 旨在将可变长度的文本拆分为单词数组 以进行进一步的全文索引处理 删除停止词 然后进行词干分析 结果似乎不错 但我想听听关于这种实现对于不同语言的文本的可靠性的意见 您会建议使用正则表达式来代替吗 请注意 我选择不使用 S
  • 为什么 C# Array.BinarySearch 这么快?

    我已经实施了一个很简单用于在整数数组中查找整数的 C 中的 binarySearch 实现 二分查找 static int binarySearch int arr int i int low 0 high arr Length 1 mid
  • 用于检查类是否具有运算符/成员的 C++ 类型特征[重复]

    这个问题在这里已经有答案了 可能的重复 是否可以编写一个 C 模板来检查函数是否存在 https stackoverflow com questions 257288 is it possible to write a c template
  • 如何使用 ICU 解析汉字数字字符?

    我正在编写一个使用 ICU 来解析由汉字数字字符组成的 Unicode 字符串的函数 并希望返回该字符串的整数值 五 gt 5 三十一 gt 31 五千九百七十二 gt 5972 我将区域设置设置为 Locale getJapan 并使用
  • 用于登录 .NET 的堆栈跟踪

    我编写了一个 logger exceptionfactory 模块 它使用 System Diagnostics StackTrace 从调用方法及其声明类型中获取属性 但我注意到 如果我在 Visual Studio 之外以发布模式运行代
  • HTTPWebResponse 响应字符串被截断

    应用程序正在与 REST 服务通信 Fiddler 显示作为 Apps 响应传入的完整良好 XML 响应 该应用程序位于法属波利尼西亚 在新西兰也有一个相同的副本 因此主要嫌疑人似乎在编码 但我们已经检查过 但空手而归 查看流读取器的输出字
  • 将 VSIX 功能添加到 C# 类库

    我有一个现有的单文件生成器 位于 C 类库中 如何将 VSIX 项目级功能添加到此项目 最终目标是编译我的类库项目并获得 VSIX 我实际上是在回答我自己的问题 这与Visual Studio 2017 中的单文件生成器更改 https s
  • 使用 WebClient 时出现 System.Net.WebException:无法创建 SSL/TLS 安全通道

    当我执行以下代码时 System Net ServicePointManager ServerCertificateValidationCallback sender certificate chain errors gt return t
  • 创建链表而不将节点声明为指针

    我已经在谷歌和一些教科书上搜索了很长一段时间 我似乎无法理解为什么在构建链表时 节点需要是指针 例如 如果我有一个节点定义为 typedef struct Node int value struct Node next Node 为什么为了
  • 转发声明和包含

    在使用库时 无论是我自己的还是外部的 都有很多带有前向声明的类 根据情况 相同的类也包含在内 当我使用某个类时 我需要知道该类使用的某些对象是前向声明的还是 include d 原因是我想知道是否应该包含两个标题还是只包含一个标题 现在我知
  • 如何在 C 中调用采用匿名结构的函数?

    如何在 C 中调用采用匿名结构的函数 比如这个函数 void func struct int x p printf i n p x 当提供原型的函数声明在范围内时 调用该函数的参数必须具有与原型中声明的类型兼容的类型 其中 兼容 具有标准定
  • 垃圾收集器是否在单独的进程中运行?

    垃圾收集器是否在单独的进程中启动 例如 如果我们尝试测量某段代码所花费的进程时间 并且在此期间垃圾收集器开始收集 它会在新进程上启动还是在同一进程中启动 它的工作原理如下吗 Code Process 1 gt Garbage Collect
  • 什么时候虚拟继承是一个好的设计? [复制]

    这个问题在这里已经有答案了 EDIT3 请务必在回答之前清楚地了解我要问的内容 有 EDIT2 和很多评论 有 或曾经 有很多答案清楚地表明了对问题的误解 我知道这也是我的错 对此感到抱歉 嗨 我查看了有关虚拟继承的问题 class B p
  • 如何查看网络连接状态是否发生变化?

    我正在编写一个应用程序 用于检查计算机是否连接到某个特定网络 并为我们的用户带来一些魔力 该应用程序将在后台运行并执行检查是否用户请求 托盘中的菜单 我还希望应用程序能够自动检查用户是否从有线更改为无线 或者断开连接并连接到新网络 并执行魔
  • 通过指向其基址的指针删除 POD 对象是否安全?

    事实上 我正在考虑那些微不足道的可破坏物体 而不仅仅是POD http en wikipedia org wiki Plain old data structure 我不确定 POD 是否可以有基类 当我读到这个解释时is triviall
  • 如何将带有 IP 地址的连接字符串放入 web.config 文件中?

    我们当前在 web config 文件中使用以下连接字符串 add name DBConnectionString connectionString Data Source ourServer Initial Catalog ourDB P
  • 是否可以在 .NET Core 中将 gRPC 与 HTTP/1.1 结合使用?

    我有两个网络服务 gRPC 客户端和 gRPC 服务器 服务器是用 NET Core编写的 然而 客户端是托管在 IIS 8 5 上的 NET Framework 4 7 2 Web 应用程序 所以它只支持HTTP 1 1 https le

随机推荐