c++:类和对象(5),运算符重载

目录

运算符重载概念:

+运算符重载

    1.成员函数重载+号 

2.全局函数重载+号

打印结果:

<<运算符重载

 递增运算符重载

简单例子

输出结果为:

 赋值运算符重载

如何重载

输出结果为:

什么时候重载 

 关系运算符重载

简单例子:

输出结果如下:

函数调用运算符重载 

简单例子

输出结果为:


运算符重载概念:

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

+运算符重载

    1.成员函数重载+号 

#include
using namespace std;

class person 
{
public:

	// 1. 成员函数重载加号运算符
    // 这里重载了加号运算符,使得两个person对象相加时,可直接通过加号进行操作
	person operator+(person& p)
	{
		person temp;
		temp.m_a = this->m_a + p.m_a; // 对m_a进行相加操作
		temp.m_b = this->m_b + p.m_b; // 对m_b进行相加操作
		return temp; // 返回相加后的结果
	}
	
	int m_a;
	int m_b;

};

void test01()
{
	person p1;
	p1.m_a = 10;
	p1.m_b = 20;
	person p2;
	p2.m_a = 10;
	p2.m_b = 20;

	person p3 = p1 + p2;  // 将p1和p2相加的结果赋值给p3

	cout << p3.m_a << endl; // 输出p3的m_a值
	cout << p3.m_b << endl; // 输出p3的m_b值
}

int main()
{
    test01(); // 调用test01函数进行测试
    system("pause"); // 暂停系统, Windows下使用

    return 0;
}

以上代码定义了一个person类,并重载了+运算符,使得两个person对象可以通过+进行相加操作。测试时创建了两个person对象p1p2,将它们相加的结果赋值给p3,然后输出p3的成员变量m_am_b的值。

2.全局函数重载+号

#include 
using namespace std;

class MyNumber 
{
private:
    int value;

public:
    MyNumber(int val) : value(val) {}

    int getValue() const { return value; }

    // 友元函数,全局函数重载加号运算符
    friend MyNumber operator+(const MyNumber& num1, const MyNumber& num2);
};

// 全局函数重载加号运算符
MyNumber operator+(const MyNumber& num1, const MyNumber& num2) 
{
    int sum = num1.value + num2.value;
    return MyNumber(sum);
}

int main() 
{
    MyNumber num1(5);
    MyNumber num2(7);

    MyNumber sum = num1 + num2; // 使用重载的加号运算符进行相加操作

    cout << "num1 = " << num1.getValue() << endl;
    cout << "num2 = " << num2.getValue() << endl;
    cout << "sum = " << sum.getValue() << endl;

    return 0;
}

打印结果:

c++:类和对象(5),运算符重载_第1张图片

在上述示例代码中,定义了一个名为MyNumber的类,其中包含一个私有成员变量value和构造函数。

为了使全局函数能够访问MyNumber类的私有成员,我们将该全局函数声明为MyNumber类的友元函数。在这个友元函数operator+中,我们重载了加号运算符,实现了两个MyNumber对象相加操作,并返回一个新的MyNumber对象作为结果。

main函数中,我们创建了两个MyNumber对象num1num2,然后使用重载的加号运算符将它们相加,将结果赋值给sum。最后,通过getValue成员函数分别输出num1num2sum的值。

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


<<运算符重载

#include 
using namespace std;

class Point 
{
private:
    int x, y;

public:
    Point(int a = 0, int b = 0) : x(a), y(b) {}

    int getX() const { return x; }
    int getY() const { return y; }

    // 友元函数,全局函数重载输出运算符
    friend ostream& operator<<(ostream& os, const Point& p);
};

// 全局函数重载输出运算符
ostream& operator<<(ostream& os, const Point& p) 
{
    os << "(" << p.x << ", " << p.y << ")";
    return os;
}

int main() 
{
    Point p(3, 5);

    cout << "The coordinates of p: " << p << endl;

    return 0;
}

输出结果为:

The coordinates of p: (3, 5)

在上述示例代码中,定义了一个名为Point的类,其中包含了两个私有成员变量xy,以及构造函数和获取成员变量的成员函数。

为了实现以自定义的方式输出Point类对象,我们重载了输出运算符<<。全局函数operator<<接受一个ostream对象os和一个Point对象p作为参数。在函数体中,我们使用os对象来输出p的坐标信息。

main函数中,我们创建了一个Point对象p,然后使用重载的输出运算符将p输出到标准输出流中。输出的结果将会是形如(3, 5)的坐标信息。


 递增运算符重载

简单例子

#include 
using namespace std;

class MyNumber 
{
private:
    int value;

public:
    MyNumber(int val) : value(val) {}

    int getValue() const 
    {
        return value;
    }

    // 重载前置递增运算符
    MyNumber& operator++() 
    {
        value++;
        return *this;
    }

    // 重载后置递增运算符
    MyNumber operator++(int) 
    {
        MyNumber temp(value);
        value++;
        return temp;
    }
};

int main() 
{
    MyNumber num(5);

    cout << "原始值:" << num.getValue() << endl;

    MyNumber preIncrement = ++num; // 前置递增运算符
    cout << "前置递增后的值:" << num.getValue() << endl;
    cout << "前置递增值:" << preIncrement.getValue() << endl;

    MyNumber postIncrement = num++; // 后置递增运算符
    cout << "后置递增后的值:" << num.getValue() << endl;
    cout << "后置递增值:" << postIncrement.getValue() << endl;

    return 0;
}

在上述示例代码中,定义了一个名为MyNumber的类,其中包含一个私有成员变量value和构造函数。

MyNumber类中,我们重载了前置递增运算符(++num)和后置递增运算符(num++)。前置递增运算符函数返回一个引用,先将value成员变量加1,然后返回递增后的对象。后置递增运算符函数接受一个额外的整型参数(通常为0),用于区分前置和后置递增运算符,创建一个临时对象保存递增前的值,然后将value成员变量加1,并返回临时对象。

注意:区别前置加加和后置加加的返回类型,看是否错误的进行了重载函数。

main函数中,我们创建了一个MyNumber对象num,然后进行前置递增运算和后置递增运算。我们将递增后的num对象的值以及返回的递增前的对象的值进行输出。

输出结果为:

原始值:5
前置递增后的值:6
前置递增值:6
后置递增后的值:7
后置递增值:6

总结:前置++返回引用,后置++返回值, 还要加参数,区别重置函数。


 赋值运算符重载

如何重载

#include 
using namespace std;

class MyClass 
{
private:
    int value;
public:
    MyClass(int val) : value(val) {}

    int getValue() const 
    {
        return value;
    }

    // 赋值运算符重载
    MyClass& operator=(const MyClass& other) 
        {
        if (this != &other) { // 检查自我赋值
            value = other.value;
        }
        return *this;
    }
};

int main() 
{
    MyClass obj1(5);
    MyClass obj2(10);

    cout << "obj1的初始值: " << obj1.getValue() << endl;
    cout << "obj2的初始值: " << obj2.getValue() << endl;

    obj1 = obj2; // 使用赋值运算符将obj2的值赋给obj1

    cout << "赋值后,obj1的值: " << obj1.getValue() << endl;

    return 0;
}

在上述示例代码中,我们在MyClass类中重载了赋值运算符(operator=)。该函数接收一个常量引用参数 other,表示赋值运算符右侧的对象。

在重载函数中,我们首先进行自我赋值检查,以避免在赋值时发生错误。然后,将other对象的值赋给this指针所指向的对象的value成员变量。

main函数中,我们创建了两个MyClass对象 obj1 和 obj2。然后使用赋值运算符将 obj2 的值赋给了 obj1。最后输出 obj1 的值进行验证。

输出结果为:

obj1的初始值: 5
obj2的初始值: 10
赋值后,obj1的值: 10

什么时候重载 

  • 当类中含有指针成员变量时,需要深拷贝对象的内容而不只是复制指针的地址。通过重载赋值运算符,可以在对象赋值时自定义深拷贝的行为,确保指针所指的资源得到正确的复制和释放。

  • 当类中存在动态分配的资源,如文件句柄、网络连接等,需要在对象赋值时确保资源的正确释放和转移。

  • 当类中含有其他类对象作为成员变量时,通过重载赋值运算符,可以实现对成员对象的赋值操作。

  • 当使用类的对象进行赋值操作时,希望自定义赋值的行为,例如执行额外的检查、记录操作日志等。


 关系运算符重载

简单例子:

#include 
using namespace std;

class Student 
{
private:
    int age;

public:
    Student(int studentAge) : age(studentAge) {}

    // 重载等于运算符
    bool operator==(const Student& other) const 
    {
        return (age == other.age);
    }

    // 重载小于运算符
    bool operator<(const Student& other) const 
    {
        return (age < other.age);
    }

    int getAge() const 
    {
        return age;
    }
};

int main() 
{
    Student s1(20);
    Student s2(18);
    Student s3(20);

    cout << "s1的年龄: " << s1.getAge() << endl;
    cout << "s2的年龄: " << s2.getAge() << endl;
    cout << "s3的年龄: " << s3.getAge() << endl;

    // 使用重载的等于运算符
    if (s1 == s2) 
    {
        cout << "s1 等于 s2" << endl;
    } 
    else 
    {
        cout << "s1 不等于 s2" << endl;
    }

    if (s1 == s3)  
    {
        cout << "s1 等于 s3" << endl;
    } 
    else 
    {
        cout << "s1 不等于 s3" << endl;
    }

    // 使用重载的小于运算符
    if (s1 < s2) 
    {
        cout << "s1 小于 s2" << endl;
    } 
    else 
    {
        cout << "s1 不小于 s2" << endl;
    }

    if (s2 < s3) 
    {
        cout << "s2 小于 s3" << endl;
    } 
    else 
    {
        cout << "s2 不小于 s3" << endl;
    }

    return 0;
}

在上述代码中,我们定义了一个 Student 类,其中包含一个私有的 age 成员变量和对应的访问器函数 getAge()

我们重载了等于运算符(==)和小于运算符(<)。在重载函数中,我们比较了两个 Student 对象之间的年龄。

在 main 函数中,我们创建了三个 Student 对象 s1s2 和 s3,并输出他们的年龄。

接下来,我们使用重载的等于运算符来比较 s1 和 s2,以及 s1 和 s3 的年龄是否相等,并输出结果。

然后,我们使用重载的小于运算符来比较 s1 和 s2,以及 s2 和 s3 的年龄大小,并输出结果。

输出结果如下:

s1的年龄: 20
s2的年龄: 18
s3的年龄: 20
s1 不等于 s2
s1 等于 s3
s1 不小于 s2
s2 小于 s3

函数调用运算符重载 

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

简单例子

#include 
using namespace std;

class MyFunction 
{
public:
    int operator()(int a, int b) 
    {
        return a + b;
    }
};

int main() 
{
    MyFunction myFunc;

    int result = myFunc(2, 3); // 调用重载的函数调用运算符
    cout << "调用结果: " << result << endl;

    return 0;
}

在上述代码中,我们定义了一个名为 MyFunction 的类,并重载了函数调用运算符 operator()。重载后的函数调用运算符将两个参数相加,并返回结果。

在 main 函数中,我们创建了 MyFunction 类的对象 myFunc。然后,我们将对象 myFunc 当作函数一样进行调用,传递两个参数,并将结果存储在 result 变量中。

输出结果为:

调用结果: 5

你可能感兴趣的:(c++之旅,c++,算法,开发语言)