2018.6.3(运算符重载)

本文通过实例介绍C++中运算符重载的概念及使用方法,包括成员函数和非成员函数两种重载方式,并提供了复数类的加法和减法运算符重载示例。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

视频教程(北大mooc):
https://www.icourse163.org/learn/PKU-1002029030?tid=1002785058#/learn/content?type=detail&id=1003870385&cid=1004682687&replay=true
菜鸟教程:
http://www.runoob.com/cplusplus/cpp-overloading.html

/*
运算符重载形式
返回值类型 operator 运算符(形参表)
{

}
*/

#include<iostream>
#include<cstdio>
#include<cmath>
using namespace std;

class Complex
{
public:
    double real,image;
public:
    Complex(double real=0,double image=0);
    void Print();
    Complex operator+(const Complex &complex1)//重载为成员函数时,参数个数为运算符目数减一
    {
        Complex complex;
        complex.real=this->real+complex1.real;
        complex.image=this->image+complex1.image;
        return complex;//返回一个临时对象
    }
};
Complex operator -(const Complex &complex1,const Complex &complex2)//重载为普通函数时,参数个数为运算符目数
{
    Complex complex;
    complex.real=fabs(complex1.real-complex2.real);//real和image须为公有成员;
    complex.image=fabs(complex1.image-complex2.image);
    return complex;//返回一个临时对象
}
Complex::Complex(double real,double image)
{
    this->real=real;
    this->image=image;
}
void Complex::Print()
{
    printf("real=%.2f,image=%.2f\n",this->real,this->image);
}
int main()
{
    Complex complex1(1,2);
    Complex complex2(3,4);
    Complex complex3(0,0);

    complex3=complex1+complex2;//等价于complex3=complex1.operator+(complex2);因为operator+定义成了成员函数;
    complex3.Print();
    complex3=complex1-complex2;//等价于complex3=operator-(complex1,complex2);因为operator-定义成了普通函数;
    complex3.Print();

    return 0;
}
<think>好的,我现在需要帮助用户了解C#中可空运算符`?.`的具体用法和示例。用户之前已经询问过JavaScript的可选链运算符,现在转向C#的类似功能。我需要结合用户提供的引用内容,整理出清晰的解释和示例。 首先,我需要确认用户提供的引用内容。引用[1]到[5]都是关于C#中各种可空运算符的,特别是`?.`。引用[3]和[4]详细提到了空条件运算符`?.`的作用,即安全访问对象成员,避免NullReferenceException。引用[5]提到了在Unity中使用时的潜在问题,即使使用`?.`也可能因为后续方法执行导致错误,这可能需要注意。 接下来,我需要组织回答的结构。用户希望知道使用方法和示例。根据之前的回答模式,应该分核心用法、典型场景、注意事项、兼容性等部分。但用户提供的引用中提到了`?.`的用法,以及与其他运算符如`??`的配合使用,还有在Unity中的特殊情况。 首先,核心用法部分需要解释`?.`的基本语法和用途,比如访问对象属性、调用方法、访问集合元素。需要引用[3]和[4]的内容,说明它如何避免NullReferenceException。 然后,典型场景可以包括处理嵌套对象、结合空合并运算符、在LINQ中的应用,以及Unity中的使用。引用[5]提到在Unity中即使使用`?.`也可能报错,需要特别说明注意事项,比如可能存在的延迟销毁问题。 注意事项部分要提到不能用于赋值、短路效应、返回值类型的变化,以及可能的性能影响。引用[5]中的例子显示,在Unity中某些情况下,即使对象为null,`?.`可能无法正确阻止方法执行,需要解释原因,比如Unity的组件销毁机制。 兼容性方面,C# 6.0及以上支持,但Unity版本可能需要检查。引用[5]提到在Unity中的问题,可能需要建议使用特定版本或处理方式。 还需要确保回答中的示例代码正确,并且符合C#语法。比如,使用可空类型时,变量声明需要`?`后缀,如`string? text = null;`。 需要对比JavaScript的可选链运算符,用户之前的问题提到过JS的`?.`,所以在回答中可以简要比较,但重点在C#。例如,C#的`?.`返回null,而JS返回undefined,但行为类似。 最后,生成相关问题,可能需要包括与其他运算符的配合使用、在Unity中的注意事项、与JS的区别等。 现在需要检查是否有遗漏点,比如`?.`在访问数组或索引器时的用法,如`list?[0]`是否正确?根据引用[3],C#中的空条件运算符包括`?[]`,所以应该提到访问集合元素时使用`?[index]`。 另外,引用[2]提到可空类型的运算结果为null,除非使用`??`,所以在结合使用`?.`和`??`时,可以给出示例,如`var result = obj?.Prop ?? defaultValue;`。 在注意事项中,要提到`a?.b.c`和`a?.b?.c`的区别,前者在a.b为null时访问c会抛出异常,后者则安全返回null。这点在引用[3]中有提到。 总结回答结构: 1. 核心用法:属性访问、方法调用、集合访问 2. 典型场景:嵌套对象、结合??、LINQ、Unity 3. 注意事项:不可赋值、短路效应、返回值类型、Unity问题 4. 兼容性:C# 6.0+,Unity版本 5. 示例代码 6. 相关问题 现在需要确保所有引用内容都被合理利用,并且回答准确、清晰。特别是用户提到的Unity中的问题,需要详细说明原因和解决方案,比如使用`?.`时,可能因为Unity的组件被标记为销毁但未完全销毁,导致引用不为null但实际无效,此时需要额外的检查。</think>#### C#可空条件运算符`?.`用法详解 C#中的可空条件运算符`?.`(Null-Conditional Operator)是C# 6.0引入的重要特性,用于简化对可能为`null`的对象成员的安全访问,避免`NullReferenceException`异常[^4]。以下是其核心用法与示例: --- ### 一、核心用法 #### 1. **安全访问对象属性/方法** 当对象可能为`null`时,`?.`会自动短路(short-circuiting),返回`null`而非抛出异常。 **传统写法**: ```csharp if (obj != null && obj.Child != null) { var value = obj.Child.Property; } ``` **使用`?.`简化**: ```csharp var value = obj?.Child?.Property; // 若任一层级为null,返回null[^3] ``` #### 2. **安全调用方法** 若方法所属对象可能为`null`,可直接用`?.`安全调用: ```csharp string? text = null; int? length = text?.Length; // length = null,而非异常[^3] ``` #### 3. **访问集合元素** 结合空条件索引运算符`?[]`,安全访问数组或列元素: ```csharp List<int>? list = null; int? firstItem = list?[0]; // firstItem = null[^1] ``` --- ### 二、典型场景示例 #### 1. **处理嵌套对象** 解析API响应时,避免深层嵌套的`null`检查: ```csharp string street = response?.Data?.User?.Address?.Street ?? "未知地址"; ``` #### 2. **结合空合并运算符`??`** 为结果提供默认值: ```csharp int age = user?.Profile?.Age ?? 18; // 若任何层级为null,默认返回18[^2] ``` #### 3. **在LINQ查询中使用** 安全处理集合中的可能为`null`的元素: ```csharp var names = users?.Select(u => u?.Name?.ToUpper()) ?? Enumerable.Empty<string>(); ``` #### 4. **Unity开发中的注意事项** Unity中若对象已被标记销毁(如`Destroy(gameObject)`),`?.`可能因延迟释放机制失效,需结合`UnityEngine.Object`判空: ```csharp // 安全写法(Unity专用) if (component != null) { component?.DoSomething(); } ``` --- ### 三、注意事项 1. **不可用于赋值** ```csharp obj?.Property = 10; // 编译错误[^1] ``` 2. **短路效应(Short-Circuiting)** 若`?.`左侧为`null`,右侧达式不会执行: ```csharp obj?.Method(CalculateValue()); // 若obj为null,CalculateValue()不执行[^4] ``` 3. **返回值类型** `?.`的返回类型为可空类型(`T?`),需显式处理或使用`??`转换: ```csharp int length = text?.Length ?? 0; // 明确处理null情况[^3] ``` 4. **Unity中的特殊行为** Unity的`UnityEngine.Object`重载了`==`运算符,可能导致`?.`误判未完全销毁的对象,建议使用显式判空: ```csharp // Unity推荐写法 if (gameObject != null) { gameObject?.GetComponent<Renderer>().material.color = Color.red; } ``` --- ### 四、兼容性 - **C#版本**:需C# 6.0及以上[^4]。 - **Unity版本**:2018.3+默认支持,旧版本需启用编译器兼容性设置[^5]。 --- #### 示例代码汇总 ```csharp // 示例1:安全访问嵌套属性 class User { public Address? Address { get; set; } } class Address { public string? Street { get; set; } } User? user = GetUser(); string street = user?.Address?.Street ?? "默认街道"; // 示例2:安全调用方法 Action? action = null; action?.Invoke(); // 无操作 // 示例3:集合元素访问 List<int>? numbers = null; int? first = numbers?[0]; // first = null ``` --- ### 相关问题 1. C#中`?.`运算符与`??`运算符如何配合使用? 2. 在Unity中为何`?.`可能无法完全避免`NullReferenceException`? 3. C#的可空引用类型(Nullable Reference Types)如何与`?.`协同工作? 4. 如何通过编译器配置启用C# 6.0特性(如`?.`)?
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值