运算符重载
与函数重载类似,C++ 的运算符也可以指定为其他的特定功能。比如:cout cin 的 << >> 就是运算符重载的实例。在实际应用中也会有很多场景:矩阵运算、向量运算、复数运算等等,虽然可以用函数来实现,运算符重载可以提高程序的可读性。
运算符重载:由关键字 operator 和其后要重载的运算符符号构成的。语法:
函数类型 operator 操作符(参数列表);
#include<iostream>
using namespace std;
class complex
{
public:
complex(){}
complex(double x,double y){this->real=x;this->imag=y;}
complex operator + (complex &x)
{
complex t;
t.real=this->real+x.real;
t.imag=this->imag+x.imag;
return t;
}
double real;
double imag;
};
int main()
{
complex a(1.2,5.6),b(3.5,6.4);
a=a+b;
cout<<a.real<<" "<<a.imag<<endl;
return 0;
}
1、运算符重载的参数个数不能随意修改,定义成类的成员函数(可以是静态和普通),也可以定义成全局,普通成员函数默认对象(this)参与运算(少一个参)
静态成员函数(全局函数类似):
static complex operator + (complex &x,complex &y)
{
complex t;
t.real=x.real+y.real;
t.imag=x.imag+y.imag;
return t;
}
2、不管是运算符重载,还是其他情况下,在对象作为参数的时候要特别注意 引用 的使用,函数调用中,实参要赋值给形参,也就是存在对象赋值,引用则可以避免这种情况。
3、“ . " (成员运算符,调用成员变量或者函数 )、“ :: " ( 作用域 )、“ ?:" (条件运算符)、“sizeof" (求字节运算符)等不能重载。
4、运算符参数类型可以根据情况设计:
complex operator + (int &x)
{
complex t;
t.real=this->real+x;
t.imag=this->imag+x;
return t;
}
调用时,要用变量(参数用了引用);
5、++ -- 有前后两种运算,为了区别,前运算重载函数默认不带参,而后运算则指定必须添加一个int类型的参数:
complex operator ++ (int x) //前运算
{
//操作尽量对this操作,避免赋值
return *this;
}
complex operator ++ () //后运算
{
return *this;
}
赋值与拷贝构造函数
对象、结构体赋值与其他数据类型不同,需要对每个分量进行赋值。如果没有重载赋值运算符,系统自动生成一个默认的,实现对分量的拷贝。
拷贝构造函数则是构造函数的一种,原型是: ClassType(const ClassType &);
#include<iostream>
using namespace std;
class complex
{
public:
complex(){} //无参构造函数
complex(double x,double y) //构造函数重载
{
this->real=x;
this->imag=y;
}
complex(const complex &x)//拷贝构造函数
{
this->real=x.real;
this->imag=x.imag;
}
double real;
double imag;
};
int main()
{
complex x; //调用无参
complex y(1.5,2.4);//调用重载的构造函数
complex z(y); //调用拷贝构造函数
x=z; //调用系统默认的赋值运算
return 0;
}
1、常量引用,const 修饰引用的对象可以避免对引用值的修改;
2、指针常量本质是常量,与整型常量一样,不能修改它的值:int * const p = &a; (常量定义的时候必须初始化),表明指针p保存a变量的地址,p不能再指向其他变量了(常量);
定义: int a,b; int * const p = &a;
p = &b; (错误 ,不能修改值) *p=10; (正确,可以修改变量的值)
3、常量指针本质是指针变量,它保存常量或者变量的地址,不能通过指针去修改变量的值(看成是常量),如:
定义:const int *p ; int a; const int b=20;
p = &a ; *p =5 ;(错误,不能通过p修改a的值) a =10; (正确)
p = &a ; p=&b; (正确,p是指针变量,可以修改值)
4、还可以写成:const int * const p = &a; 则既不能修改p的值(指向其他变量),又不允许修改指向的变量的值。
5、深拷贝与浅拷贝,这个概念对C/C++程序员基本上比较好理解,而其他不包含指针的高级语言就相对比较麻烦:这里涉及到指针,区别比较容易理解。所谓浅拷贝只是对指针赋值,而深拷贝则是针对内容进行复制;找了一个例子:
#include <iostream>
using namespace std;
class A
{
public:
A(int _size) : size(_size){ data = new int[size]; } //假如其中有一段动态分配的内存
int Get_Val() {return *data;}
int *Get_Val_add() { return data; }
A() {}
A( const A& _A) : size(_A.size){ data = new int[size]; } //深拷贝
~A(){delete[] data; data = NULL; } //析构时释放资源
public:
int *data;
int size;
};
int main()
{
A a(5);
A b(a);
cout << a.data << endl;
cout << b.data << endl;
return 0;
}
很明显看到深拷贝是重新new了空间,data值不同。如果屏蔽深拷贝函数(系统默认)则data项相同,同时,程序会报错(a、b销毁时都调用析构函数,执行了两次delete)。