多态:同一种形为,不同的对象得到不同的结果;(按这里的定义来看,不一定是函数,可以是运算符) //运算符应该是重载,多态才是覆盖,重载不能算 是多态;上面的辩证法可能 有问题??
静态多态(运算符重载,函数重载)
一、运算符重载
Complex obj1,obj2,obj3;
obj1 = 3;
obj3 = obj2;
obj3 = obj1 + obj2;
cout<< obj1<<obj2<<endl;
上面的运算符,默认情况下是无法实现的,因此需要为自定义的类实现自己的运算符;
运算符重载:对已有的功能赋以其另一种功能,以适用于不同的数据类型;
重载不能修改优先级和结合性!重载的功能应与原功能相似;
不可以重载的运算符有: . .* :: ?:
运算符重载可以通过定义类的成员函数或是友元函数实现
成员函数重载运算符:
返回类型 类名::operator运算符(形参列表)
{
}
<span style="font-size:24px;">complex operator+(const complex& m) const; </span>
<span style="font-size:24px;"><span style="color:#ff0000;">//这里用2个const 是因为外面的const修饰thist,并不是说m不可以改变</span>
complex a(1,2);
complex b(2,3);
complex c = a +b; /// 运算符左操作符是调用函数的对象,右操作数是参数 a.operator+(b); </span>
/// 使用成员函数重载运算符,左操作数要求是类本身对象,而右操作数可以为其它类型 如上面参数为int
// 这时可以再次重载,参数传int ,实现 b = a + 3;
显然,成员函数无法实现 b = 3 + a
友元全局函数重载运算符:
friend 返回值类型 operator运算符(形参列表) // 二元操作要两个形参,一元操作为空形参列表
{
}
friend complex operator+(const Complex &a, const Complex &b);
// 用友元的意义是为了能访问类的私有成员,如果私有成员都有接口,那可以不用友元
b = 3 + a是可以用全局函数实现!
建议:二元操作用友元全局函数实现; 如果第一个操作数要求是本类对象,推荐用成员函数,如果第一 个数肯定不是本类对象,推荐用友元函数实现
特定的运算符:
1. 只能用成员函数实现的运算符:(第一个操作数一定要是本类对象)
= , (), [ ], -> :如= 如果用a = b ,则本类对象是a,b = a 的本类对象是b;a 与b 的类型可能不同;
2. 只能使用友元函数实现的:(第一个操作数一定不是本类对象)
>> , << (输入输出)
二、常用运算符重载
单目:++, -- //推荐使用成员函数
++a;
成员函数:
Complex & operator++() // 返回必须是本类对象的引用,返回引用则可以作左值: ++a = 3; // a = 3;
{
++m_real;
++m_imag;
return *this; // 左值看成返回本身
}
a++;
Complex operator++ (int) // int 没有任何意义
{
Complex temp(*this);
++m_real;
++m_imag;
return temp;
}
友元全局函数:
Complex &operator--(Complex& a) // --a;
{
a.m_real ++;
a.m_imag ++
return ax;
}
双目运算符:
1. >> 、<<
cout<<a; cin>>a; 第一个操作数都不是本类对象;因此要用到友元全局函数;
cout << a << b; // 说明返回值是可以做左值的,即要返回引用ostream类型;
friend istream& operator>>(istream& in, 用户类型& obj) // obj用&可以不用干枯析内存
{
in >> obj.x;
in >> obj.y;
return in;
}
friend ostream & operator<<(ostream& out, const 用户类型& obj)
{
out<<obj.x;
return out;
}
cin>>a>>b; // operator>>((operator(cin,a)),b);
2. 赋值运算符重载
// 当类要定义析构函数(指针成员被删2次)的时候要定义拷贝构造函数(深拷贝)与=运算符重载
Complex& operator=(const Complex& ref);
=运算符只能定义成成员函数重载,即即一个操作数必须为类对象;
=不定义系统会生成一个默认的,这会造成浅拷贝的问题;
在子类中要显式的调用直接基类的=运算符!!!
class A
{
int a;
};
class B:public A
{
int b;
};
B& operator=(B& ref) // 有两部分要赋值:A类中的a,B类中的b;
{
A::operator=(ref); // 子类赋给A类
b = ref.b;
return *this;
}
com a;
com b = a; // 初始化拷贝构造函数
com c;
c = a; // =运算符重载
3. 下标运算符[ ]
TYPE & operator[ ](const int aIndex); // TYPE存储的数据类型
重载new, delete运算符
void 类名::operator delete(void*, [arg_list]);
若有第二个参数,必须为size_t
重载类型转换运算符:
Length obj1(1000);
double m = double(obj1); // double m = obj1.operator double(); 显示调用的结果
m = obj1; // m = obj1.operator double(); //隐示调用
operator<强制转换的目标类型>() // 无参数(只转换自身),无返回值
{
// 定义后,可以显式调用或是隐式调用
}
可以通过构造函数实现类型转换:
Complex(int b);
void foo(Complex com);
int b= 5; foo(b); // b 被转换成了Complex类型
operator int(); // 强制类型转换
上面两个红色的过程,都完成了类型转换,同时转换会出现二义性!即foo(b);不知道调用 哪个函数完成类型转换
总结
1. 赋值运算符重载; com = coo; // com.operator=(const Coordinate& coo);
2. 构造函数; com = coo; // 先调用Complex::Complex(const Coordinate& coo);再用赋值运算符=赋给com
3. 类型转换运算符(); com = coo; // 在Coordinate类中实现: operator Complex() const; 先调用Coordinate类中的类型转换运算符,再调用Complex类的赋值运算符
#ifndef TEST
#define TEST
#include <iostream>
#include <string>
using namespace std;
class B;
class A;
extern ostream& operator<<(ostream& in,const A&a);
extern ostream& operator<<(ostream& in,const B&a);
class A
{
public:
int x;
int y;
friend ostream& operator<<(ostream& out,const A&a);
A():x(5),y(10){};
// A(B& b); // 构造函数完成类型转换
A& operator=(const B& b); // 赋值运算符完成类型转换
};
class B
{
public:
string str1;
string str2;
B():str1("123.5"),str2("55.5"){};
friend ostream& operator<<(ostream& out,const B&a);
operator A();
};
#endif
#include "testmain.h"
#include <iostream>
#include <string>
using namespace std;
// 强制类型转换
ostream& operator<<(ostream& out, A&a)
{
out << "A的值为:" << a.x<<" "<<a.y;
return out;
}
ostream& operator<<(ostream& out,const B&a)
{
out<<"B: "<<a.str1<<" "<<a.str2;
return out;
}
/*
A::A(B& b)
{
cout<<"开始调用构造函数转换B->A:"<<b<<endl;
x = atoi(b.str1.c_str());
y = atoi(b.str2.c_str());
cout<<"构造函数转换成功后:"<<x<<" "<<y<<endl;
}*/
A& A::operator=(const B& b)
{
cout<<"开始调用赋值运算符转换B->A:"<<b<<endl;
x = atoi(b.str1.c_str()) + 1;
y = atoi(b.str2.c_str()) + 1;
cout<<"赋值运算符转换成功后:"<<x<<" "<<y<<endl;
return *this;
}
B::operator A()
{
cout<<"开始调用强制类型转换运算符转换B->A"<<endl;
A a;
a.x = atoi(str1.c_str()) + 10;
a.y = atoi(str2.c_str()) + 10;
cout<<"强制类型转换运算符转换成功后:"<<a.x<<" "<<a.y<<endl;
return a;
}
int main()
{
A a;
B b;
cout<<b<<endl;
cout<<a<<endl;
a = b;
cout<<"_____________________"<<endl;
B c;
a = A(c);
cout<<a<<endl;
}