C++ 语法基础(四)(三)

简介: C++ 语法基础(四)(三)

运算符重载

什么是运算符重载


使系统内置的运算符可以用于类类型


例如:类A的对象a1、a2、a3,可以执行


a3 = a1 + a2;


运算符重载的方法


运算符重载就是写一个函数解释某个运算符在某个类中的含义


关键问题


如何使编译器能自动找到重载的这个函数


解决方案


函数名必须要体现出和某个被重载的运算符的联系。


C++中规定,重载函数名为 operator@. 其中,@为要重载的运算符


重载“+”运算符,该重载函数名为operator+


重载赋值运算符,函数名为operator=


函数原型 运算符的重载不能改变运算符的运算对象数


形式参数个数(包括成员函数的隐式指针this)及类型与运算符的运算对象相符


返回值与运算结果值类型一致


成员函数vs全局函数


大多数运算符的重载函数可以写成成员函数,也可以写成全局函数


重载成全局函数 函数原型与运算符与完全相符 最好将此函数设为友员函数


重载成成员函数 形式参数个数比运算符的运算对象数少1。这是因为成员函数有一个隐含的参数this 隐含参数this是第一个形式参数


image.png


重载实例

重载实例


为rational类增加“+”和“*”以及“==”比较的重载函数,用以替换现有的add和multi函数


方案一:重载成成员函数

class Rational
{
private:
     int num;
     int den;
     void ReductFraction();
public:
     Rational(int n = 0, int d = 1)
    {
         num = n;
         den = d;
    }
     Rational operator+(const Rational &r1) const;
     Rational operator*(const Rational &r1) const;
     bool operator==(const Rational &r1) const;
     void display()
    {
         cout << num << '/' << den;
    }
};


函数实现

Rational Rational::operator+(const Rational &r1) const
{
    Rational tmp;
    tmp.num = num * r1.den + r1.num * den;
    tmp.den = den * r1.den;
    tmp.ReductFraction();
    return tmp;
}
Rational Rational::operator*(const Rational &r1) const
{
    Rational tmp;
    tmp.num = num * r1.num;
    tmp.den = den * r1.den;
    tmp.ReductFraction();
    return tmp;
}
bool Rational::operator==(const Rational &r1) const
{
    return num == r1.num && den == r1.den;
}

方案二:重载成友员函数


class Rational
{
     friend Rational operator+(const Rational &r1, const Rational &r2);
     friend Rational operator*(const Rational &r1, const Rational &r2);
     friend bool operator==(const Rational &r1, const Rational &r2);
private:
     int num;
     int den;
     void ReductFraction();
public:
     Rational(int n = 0, int d = 1)
    {
        num = n;
        den = d;
    }
     void display() { cout << num << '/' << den; }
};


函数实现

Rational operator+(const Rational &r1, const Rational &r2)
{
    Rational tmp;
    tmp.num = r1.num * r2.den + r2.num * r1.den;
    tmp.den = r1.den * r2.den;
    tmp.ReductFraction();
    return tmp;
}
Rational operator*(const Rational &r1, const Rational &r2)
{
    Rational tmp;
    tmp.num = r1.num * r2.num;
    tmp.den = r1.den * r2.den;
    tmp.ReductFraction();
    return tmp;
}


其他函数实现略


重载后有理数类的使用

int main()
{
    Rational r1(1, 6), r2(1, 6), r3;
    r3 = r1 + r2;
    r1.display();
    cout << " + ";
    r2.display();
    cout << " = ";
    r3.display();
    cout << endl;
    r3 = r1 * r2;
    r1.display();
    cout << " * ";
    r2.display();
    cout << " = ";
    r3.display();
    cout << endl;
    return 0;
}
//题目描述:
//补全Int类,使得程序的输出为:
//1
//2
//3
//4
//5
#include <iostream>
using namespace std;
class Int
{
    static int addtime;
public:
    Int(int x) {}
    friend int operator+(const Int &r1, const Int &r2)
    {
        return ++addtime;
    }
};
int Int::addtime = 0;
int main()
{
    Int a(1), b(1), c(1);
    cout << a + a << endl;
    cout << b + b << endl;
    cout << b + c << endl;
    cout << c + c << endl;
    cout << a + a << endl;
}


组合

对象成员

聚集关系,是一种部分和整体的关系,即has-a的关系

组合的目的:简化创建新类的工作,让创建新类的程序员不需要过多地关注底层的细节,可以在更高的抽象层次上考虑问题,有利于创建功能更强的类。


image.png

继承

c++派生类定义的格式如下:

class 派生类名:继承方式 基类名{
  新增加的成员声明;
};

继承方式可以是public、private和protected


派生类中基类成员的访问特性


image.png

image.png

image.png


多态性

多态性有两种实现方式:编译时的多态性和运行时的多态性

运算符重载和函数重载属于编译时的多态性

虚函数属于运行时的多态性

image.png

相关文章
|
12天前
|
编译器 C++ 容器
C++语言的基本语法
想掌握一门编程语言,第一步就是需要熟悉基本的环境,然后就是最重要的语法知识。 C++ 程序可以定义为对象的集合,这些对象通过调用彼此的方法进行交互。现在让我们简要地看一下什么是类、对象,方法、即时变量。 对象 - 对象具有状态和行为。例如:一只狗的状态 - 颜色、名称、品种,行为 - 摇动、叫唤、吃。对象是类的实例。 类 - 类可以定义为描述对象行为/状态的模板/蓝图。 方法 - 从基本上说,一个方法表示一种行为。一个类可以包含多个方法。可以在方法中写入逻辑、操作数据以及执行所有的动作。 即时变量 - 每个对象都有其独特的即时变量。对象的状态是由这些即时变量的值创建的。 完整关键字
29 2
|
1月前
|
Java 编译器 程序员
C++中的语法知识虚继承和虚基类
**C++中的多继承可能导致命名冲突和数据冗余,尤其在菱形继承中。为解决这一问题,C++引入了虚继承(virtual inheritance),确保派生类只保留虚基类的一份实例,消除二义性。虚继承通过`virtual`关键字指定,允许明确访问特定路径上的成员,如`B::m_a`或`C::m_a`。这样,即使基类在继承链中多次出现,也只有一份成员副本,简化了内存布局并避免冲突。虚继承应在需要时提前在继承声明中指定,影响到从虚基类派生的所有后代类。**
44 7
|
1月前
|
编译器 C++ 开发者
C++一分钟之-属性(attributes)与属性语法
【7月更文挑战第3天】C++的属性(attributes)自C++11起允许附加编译器指令,如`[[nodiscard]]`和`[[maybe_unused]]`,影响优化和警告。注意属性放置、兼容性和适度使用,以确保代码清晰和可移植。示例展示了如何使用属性来提示编译器处理返回值和未使用变量,以及利用编译器扩展进行自动清理。属性是提升代码质量的工具,但应谨慎使用。
49 13
|
2月前
|
编译器 程序员 C++
C++一分钟之-属性(attributed)与属性语法
【6月更文挑战第28天】C++的属性为代码添加元数据,帮助编译器理解意图。C++11引入属性语法`[[attribute]]`,但支持取决于编译器。常见属性如`nodiscard`提示检查返回值,`maybe_unused`防止未使用警告。问题包括兼容性、过度依赖和误用。使用属性时需谨慎,确保团队共识,适时更新以适应C++新特性。通过示例展示了`nodiscard`和`likely/unlikely`的用法,强调正确使用属性能提升代码质量和性能。
52 13
|
2月前
|
编译器 C语言 C++
|
2月前
|
存储 自然语言处理 编译器
【C++语言1】基本语法
【C++语言1】基本语法
|
3月前
|
编译器 C语言 C++
C++的基本特性和语法
C++的基本特性和语法
46 1
|
3月前
|
存储 C++ 容器
【C++从练气到飞升】09---string语法指南(二)
【C++从练气到飞升】09---string语法指南(二)
|
3月前
|
存储 Linux C语言
【C++从练气到飞升】09---string语法指南(一)
【C++从练气到飞升】09---string语法指南(一)