运算符重载概念
所谓重载,就是重新赋予新的含义。函数重载就是对一个已有函数赋予新的定义,使之实现新的功能,因此,一个函数名就可以用来代表不同功能的函数,也就是“一名多用”。
运算符也可以重载,运算符重载的本质是一个函数。
class Complex
{
public:
int a;
int b;
friend Complex operator+(Complex &c1, Complex &c2);
public:
Complex(int a=0, int b=0)
{
this->a = a;
this->b = b;
}
public:
void printCom()
{
cout<<a<<" + "<<b<<"i "<<endl;
}
};
/*
Complex myAdd(Complex &c1, Complex &c2)
{
Complex tmp(c1.a+ c2.a, c1.b + c2.b);
return tmp;
}
*/
Complex operator+(Complex &c1, Complex &c2)
{
Complex tmp(c1.a+ c2.a, c1.b + c2.b);
return tmp;
}
void main()
{
Complex c1(1, 2), c2(3, 4);
//Complex c3 = c1 + c2; //用户自定义类型 编译器无法让变量相加
//Complex myAdd(Complex &c1, Complex &c2);
//1 普通函数
//Complex c3 = myAdd(c1, c2);
//c3.printCom();
//2 operator+ 函数名称
//Complex c3 = operator+(c1, c2);
//c3.printCom();
//3 +替换 函数名
Complex c3 = c1 + c2; //思考C++编译器如何支持操作符重载机制的 (根据类型)
c3.printCom();
{
int a =0, b = 0, c; //基础类型C++编译器知道如何加减
c = a +b;
}
//4 把Complex类变成私有属性
//友元函数的应用场景
//friend Complex operator+(Complex &c1, Complex &c2);
cout<<"hello..."<<endl;
system("pause");
return ;
}
重载运算符的限制
重载运算符可以对运算符作出新的解释,但是原有的基本语义不变。不改变运算符的优先级,不改变运算符的结合性,不改变运算符所需要的操作数,不能创建新的运算符。
运算符编程基础
友元函数实现操作符重载的应用场景
1)友元函数和成员函数选择方法
当无法修改左操作数的类时,使用全局函数进行重载。
=,[],(),->操作符只能通过成员函数进行重载。
2)用友元函数重载<<,>> 操作符
istream和ostream是C++的预定义流类,cin是istream的对象,cout是ostream的对象。
运算符<<由ostream重载为插入操作,用于输出基本数据类型。
运算符>>有istream重载为提取操作,用于输入基本数据类型。
通过友元函数重载<<和>>,输出和输入用户自定义的数据类型。
ostream& operator<<(ostream &out, Complex &c1)
{
//out<<"Hello World"<<endl;
out << c1.a << " + " << c1.b << "i " <<endl;
return out;
}
cout.operator<<(c1).operator<<("abcd");
实际上的调用语句可以看做是上面这句话,类成员函数方法是没有办法实现<<操作符重载的,因为cout需要函数返回值充当左值,返回一个ostream引用。
3)友元函数重载操作符注意点
友元函数重载运算符常用于运算符的左右操作数类型不同的情况。
在第一个参数需要隐式转换的情况下,使用友元函数重载运算符是正确的选择。
友元函数没有this指针,所需操作数都必须在参数表显式声明,很容易实现类型的隐式转换。
C++中不能用友元函数重载的运算符有:=、()、[]、->
运算符重载提高
重载运算符 =
赋值运算符重载用于对象数据的复制,operator=必须重载为成员函数。
重载函数原型为:
类型 & 类名 :: operator(const 类名 &)
重载数组下表运算符[]
重载[]和()运算符,是二元运算符。[]和()只能用成员函数重载,不能用友元函数重载。
重载函数调用符()
类型 类 :: operator() (表达式表);
#include <iostream>
class F
{
public :
double operator()( double x , double y );
};
double F::operator()(double x, double y)
{
return x * x + y * y ;
}
int main()
{
F f ;
f.getA();
cout << f ( 5.2 , 2.5 ) << endl ; // f . operator() (5.2, 2.5)
}
为什么不重载&&和||运算符
&&和||是C++当中非常特殊的操作符,&&和||内置实现了短路规则,操作符重载是靠函数重载来完成的。操作数作为函数参数传递,C++的函数参数都会被求值,无法实现短路规则。
运算符重载在项目开发中的应用
实现字符串类
#pragma once
#include <iostream>
class MyString
{
public:
MyString(int len);
MyString(const char *p); //构造
MyString(const MyString& s); //拷贝
~MyString();
public:
MyString& operator=(MyString& ms);
char& operator[](int i);
bool operator==(MyString& ms);
bool operator!=(MyString& ms);
bool operator>(MyString& ms);
bool operator<(MyString& ms);
friend void operator<<(std::ostream& out, MyString& ms);
friend void operator>>(std::istream& in, MyString& ms);
public:
char* ptr_space();
void delete_space();
private:
char* m_space;
int length = 0;
};
#include "MyString.h"
#include <iostream>
void operator<<(std::ostream& out, MyString& ms)
{
out << ms.m_space;
}
void operator>>(std::istream& in, MyString& ms)
{
in >> ms.m_space;
}
MyString::MyString(int len)
{
this->length = len;
this->m_space = new char[this->length + 1];
strcpy_s(this->m_space, this->length + 1, " ");
}
MyString::MyString(const char* p)
{
if (p == nullptr)
{
this->length = 0;
m_space = new char[this->length + 1];
strcpy_s(this->m_space,this->length + 1, "");
}
else
{
this->length = strlen(p);
m_space = new char[this->length + 1];
strcpy_s(m_space, this->length + 1, p);
}
}
MyString::~MyString()
{
delete[] m_space;
}
MyString::MyString(const MyString& s)
{
this->length = s.length;
this->m_space = new char[this->length + 1];
strcpy_s(this->m_space, this->length + 1, s.m_space);
}
MyString& MyString::operator=(MyString& ms)
{
if (this->m_space != nullptr)
{
delete[] m_space;
this->length = 0;
}
this->length = ms.length;
this->m_space = new char[this->length + 1];
strcpy_s(this->m_space, this->length + 1, ms.m_space);
return *this;
}
char& MyString::operator[](int i)
{
return this->m_space[i];
}
bool MyString::operator==(MyString& ms)
{
if (strcmp(this->m_space, ms.m_space) == 0)
{
return true;
}
else
{
return false;
}
}
bool MyString::operator!=(MyString& ms)
{
if (strcmp(this->m_space, ms.m_space) != 0)
{
return true;
}
else
{
return false;
}
}
bool MyString::operator>(MyString& ms)
{
if (strcmp(this->m_space, ms.m_space) == 1)
{
return true;
}
else
{
return false;
}
}
bool MyString::operator<(MyString& ms)
{
if (strcmp(this->m_space, ms.m_space) == -1)
{
return true;
}
else
{
return false;
}
}
char* MyString::ptr_space()
{
return this->m_space;
}
void MyString::delete_space()
{
this->length = 0;
delete[] this->m_space;
}
//测试
#include <iostream>
#include "MyString.h"
using namespace std;
int main()
{
MyString s1(12);
MyString s2("asdfzcx");
MyString s3(2);
s3 = s2;
cout << s1 ;
cout << endl;
cout << s2 ;
cout << endl;
cout << s3 ;
cout << endl;
cout << s2[2];
cout << endl;
if (s2 == s3)
{
cout << "s3等于s2" << endl;
}
if (s1 < s2)
{
cout << "s1小于s2" << endl;
}
if (s2 > s1)
{
cout << "s2大于s1" << endl;
}
if (s1 != s2)
{
cout << "s1不等于s2" << endl;
}
char* p = s2.ptr_space();
//s2.delete_space();
if (p == nullptr)
{
cout << "准备打印";
cout << p << endl;
}
//cout << "p被释放";
cout << p;
}