运算符重载
友元函数是定义在类外部,但有权访问类的所有私有(private)成员和保护(protected)成员。 尽管友元函数的原型有在类的定义中出现过,但是友元函数并不是成员函数。
friend 返回值类型 函数名(参数列表);
friend void global_printf(const Point&that); //友元函数
友元类的所有成员函数都是另一个类的友元函数,都可以访问另一个类中的隐藏信息(包括私有成员和保护成员)
//类前面加上friend声明友元类
class Point
{
int m_x;
int m_y;
public:
friend class Point3D;//友元类
};
class Point3D
{
Point m_p;
int m_z;
public:
};
注意事项:
若类B是类A的友元。则只有类B的成员函数可以访问类A中的隐藏信息
若类B是类A的友元,类A不一定是类B的友元,要看在类中是否有相应的声明。
若类B是类A的友元,类C是B的友元,类C不一定是类A的友元,同样要看类中是否有相应的申明
//demo1.cpp
#include<iostream>
using namespace std;
class Point
{
int m_x;
int m_y;
public:
Point(int x = 0, int y = 0); //缺省构造函数 类内声明类外定义
void Point_printf(); //类内数据打印函数
friend void global_printf(const Point&that); //友元函数 类外数据打印函数
friend class Point3D; //友元类
};
class Point3D
{
Point m_p;
int m_z;
public:
Point3D(int x = 0, int y = 0, int z = 0);
void Point3D_printf();
};
int main()
{
Point point(10,20);
cout << "========类函数打印========" << endl;
point.Point_printf();
cout << "========友元函数打印========" << endl;
global_printf(point);
cout << "========友元类打印========" << endl;
Point3D point3d(10, 20, 30);
point3d.Point3D_printf();
cin.get();
return 0;
}
Point::Point(int x, int y)
{
m_x = x;
m_y = y;
}
void Point::Point_printf()
{
cout << this->m_x << " " << this->m_y << endl;
}
void global_printf(const Point&that)
{
cout << that.m_x << " " << that.m_y << endl;
}
Point3D::Point3D(int x, int y, int z)
{
m_p.m_x = x;
m_p.m_y = y;
m_z = z;
}
void Point3D::Point3D_printf()
{
cout << m_p.m_x << " " << m_p.m_y << " " << m_z << endl;
}
打印结果:
========类函数打印========
10 20
========友元函数打印========
10 20
========友元类打印========
10 20 30
运算符重载,就是对已有的运算符重新进行定义,赋予其另一种功能,以适应不同的数据类型。
重载运算符可以使用成员函数或非成员函数(一般是友元函数)两种方法
只能使用其中的一种方法
类名 operator运算符(const 类名& other);//成员函数实现
Complex operator+(const Complex& other);
双目算术运算符 | + (加),-(减),*(乘),/(除),% (取模) |
---|---|
关系运算符 | ==(等于),!= (不等于),< (小于),> (大于>,<=(小于等于),>=(大于等于) |
逻辑运算符 | ||(逻辑或),&&(逻辑与),!(逻辑非) |
单目运算符 | + (正),-(负),*(指针),&(取地址) |
自增自减运算符 | ++(自增),--(自减) |
位运算符 | | (按位或),& (按位与),~(按位取反),^(按位异或),,<< (左移),>>(右移) |
赋值运算符 | =, +=, -=, *=, /= , % = , &=, |=, ^=, <<=, >>= |
空间申请与释放 | new, delete, new[ ] , delete[] |
其他运算符 | ()(函数调用),->(成员访问),,(逗号),[](下标) |
Complex operator+(const Complex& other);//+运算符重载 成员函数实现
friend Complex operator-(const Complex&A, const Complex&B);//-运算符重载 非成员函数实现
如果没有重载赋值运算符,操作系统会有缺省运算符重载,编译器提供的默认拷贝赋值操作符重载,同默认拷贝构造一样,默认拷贝赋值操作符重载同样是浅拷贝。
Complex operator=(const Complex&other); //=运算符重载 成员函数实现
//为了简便,只实现=运算符的避免自赋值,更多请看string类
Complex operator=(const Complex&other)
{
if (&other != this) //防止自赋值
{
m_real = other.m_real;
m_imaginary = other.m_imaginary;
}
return *this;
}
Complex operator++(); //前++运算符重载 成员函数实现
Complex operator++(int); //后++运算符重载通过哑元实现 成员函数实现
cout是输出类的对象,而cin是输入类的对象,C++头文件iostream取自istream和ostream之意
流操作符>>,<<一般使用非成员函数实现,也就是友元函数实现,这样可以符合程序员的惯性思维
friend ostream &operator<<(ostream &os, const Complex&other);//IO流运算符重载函数一般声明为类的友元函数
friend istream &operator >> (istream &is, Complex&other); //类的非成员函数重载>>提取运算符
让我们来看一下如果使用类成员方法重载流操作运算符会怎样一个结果
istream &operator>>(istream &is); //类的成员函数重载>>提取运算符
这样定义的话使用的时候
Complex test;
test >> cin; //类的成员函数提取运算符的调用
跟自己使用cin不太一样对不对,就像一个反人类的设计..
//demo_2.cpp
#include<iostream>
using namespace std;
#define IS_MEMBER 0
class Complex
{
double m_real;
double m_imaginary;
public:
Complex(double r = 0, double i = 0);
void Complex_show();
Complex operator+(const Complex& other); //+运算符重载 成员函数实现
Complex operator=(const Complex&other); //=运算符重载 成员函数实现
Complex operator++(); //前++运算符重载 成员函数实现
Complex operator++(int); //后++运算符重载 成员函数实现
friend Complex operator-(const Complex&A, const Complex&B); //-运算符重载 非成员函数实现
friend ostream &operator<<(ostream &os, const Complex&other);//IO流运算符重载函数一般声明为类的友元函数
#if IS_MENBER
istream &operator>>(istream &is); //类的成员函数重载>>提取运算符
#else
friend istream &operator >> (istream &is, Complex&other); //类的非成员函数重载>>提取运算符
#endif
};
int main()
{
Complex complex_1(1, 8), complex_2(2, 5), temp;
cout << "===========+操作符重载===========" << endl;
temp = complex_1 + complex_2;
temp.Complex_show();
cout << "===========流操作符重载===========" << endl;
Complex test;
#if IS_MENBER
test >> cin; //类的成员函数提取运算符的调用
#else
cin >> test;
#endif
complex_1 = test;
cout << "===========-操作符重载===========" << endl;
temp = complex_1 - complex_2;
cout <<"temp:"<< temp << endl;
cout << "============前++后++==========" << endl;
Complex complex_3(1, 1);
cout << complex_3++;
cout << complex_3;
cout << ++complex_3;
return 0;
}
Complex::Complex(double r, double i)
{
m_real = r;
m_imaginary = i;
}
void Complex::Complex_show()
{
cout << m_real << "+" << m_imaginary << "i" << endl;
}
Complex Complex::operator+(const Complex & other)
{
Complex temp;
temp.m_real = this->m_real + other.m_real;
temp.m_imaginary = this->m_imaginary + other.m_imaginary;
return temp;
}
Complex Complex::operator=(const Complex & other)
{
if (&other != this)
{
m_real = other.m_real;
m_imaginary = other.m_imaginary;
}
return *this;
}
Complex Complex::operator++()
{
this->m_real = this->m_real + 1;
return *this;
}
Complex Complex::operator++(int)
{
Complex temp = *this;
this->m_real = this->m_real + 1;
return temp;
}
#if IS_MENBER
istream & Complex::operator >> (istream & is)
{
cin >> this->m_real >> this->m_imaginary;
// TODO: 在此处插入 return 语句
return is;
}
#else
istream & operator >> (istream & is, Complex & other)
{
is >> other.m_real >> other.m_imaginary;
// TODO: 在此处插入 return 语句
return is;
}
#endif
Complex operator-(const Complex & A, const Complex & B)
{
Complex temp;
temp.m_real = A.m_real - B.m_real;
temp.m_imaginary = A.m_imaginary - B.m_imaginary;
return temp;
}
ostream & operator<<(ostream & os, const Complex & other)
{
os << other.m_real << "+" << other.m_imaginary << "i" << " ";
// TODO: 在此处插入 return 语句
return os;
}
//运行结果
===========+操作符重载===========
3+13i
===========流操作符重载===========
4 5
===========-操作符重载===========
temp:2+0i
============前++后++==========
1+1i 2+1i 3+1i
//类内实现new运算符重载 new的返回值必须是void* 第一个参数必须为size_t
void* operator new(size_t size);//类的非成员函数重载new
//类内实现new运算符重载 new的返回值必须是void* 第一个参数必须为void*
void operator delete(void* ptr);//类的非成员函数重载delete
注意:对于new的重载返回值必须是void*;delete的重载返回值一定是void
//demo_3.cpp
#include<iostream>
using namespace std;
class Integer
{
char* m_str;
int m_len;
public:
Integer()
{
m_len = 1;
m_str = new char[m_len];
m_str[0] = '\0';
}
Integer(const char* str)
{
m_len = strlen(str) + 1; //这个1留给\0
m_str = new char[m_len];
strcpy(m_str, str);
}
char & operator[](int i);
//类内实现new运算符重载 new的返回值必须是void* 第一个参数必须为size_t
void* operator new(size_t size)
{
return (Integer*)malloc(size);
}
//类内实现new运算符重载 new的返回值必须是void* 第一个参数必须为void*
void operator delete(void* ptr)
{
free(ptr);
}
friend ostream &operator<<(ostream &os, const Integer&other);
};
int main()
{
Integer* arr = new Integer("hello world!");
cout << *arr << endl;
Integer str("hello C++!");
for (int i = 0; i <= 10; i++)
{
cout << str[i];
}
delete arr;
cin.get();
return 0;
}
ostream & operator<<(ostream & os, const Integer & other)
{
cout << other.m_str;
// TODO: 在此处插入 return 语句
return os;
}
char & Integer::operator[](int i)
{
//TODO: 在此处插入 return 语句
return m_str[i];
}
//运行结果
hello world!
hello C++!
End