函数与运算符重载
函数重载
c++产生函数符号的时候,由函数名+参数列表类型组成的。
c产生函数符号的时候,由函数名来决定,不支持重载。
定义
函数重载
- 一组函数函数名相同
- 参数列表的个数或类型不同
Tips:
一组函数,函数名相同,参数列表也相同,仅仅是返回值不同,这个不叫重载。
bool compare(int a,int b)
{cout<<"compare_int_int"<<endl;return a>b;
}
bool compare(double a,double b)
{cout<<"compare_double_double"<<endl;return a>b;
}bool compare(const char * a,const char * b)
{cout<<"compare_char *char *"<<endl;return strcmp(a,b)>0;
}int main() {compare(10, 20);compare(100.0, 20.0);compare("aaa", "ccc");
}
作用域
一组函数要称得上重载,一定是处在同一个作用域中的。
作用域概念
int data=10;
int main()
{int data=20; //main函数内的局部作用域int a=::data;//全局作用域int b=data;
}
局部作用域函数声明覆盖全局作用域函数模板
bool compare(int a,int b)
{cout<<"compare_int_int"<<endl;return a>b;
}
bool compare(double a,double b)
{cout<<"compare_double_double"<<endl;return a>b;
}bool compare(const char * a,const char * b)
{cout<<"compare_char *char *"<<endl;return strcmp(a,b)>0;
}int main() {bool compare(int a,int b);//加了这一句申明//compare由全局作用域变成了局部作用域,即局部作用域只有compare(int a,int b)这个函数,会报错compare(10, 20);compare(100.0, 20.0);compare("aaa", "ccc");
}
修改代码
int main() {bool compare(int a,int b);//加了这一句申明//compare由全局作用域变成了局部作用域,即局部作用域只有compare(int a,int b)这个函数,会报错compare(10, 20);::compare(100.0, 20.0); //使用全局作用域解析符::compare("aaa", "ccc"); //使用全局作用域解析符
}
总结
:不同作用域的函数是不会发生重载的
形参区别
const(volatile)影响形参类型
void fun(int a) {};
void fun(const int a) {};
//这里的const没有起作用,两个函数本质上都是void fun(int a)
int 和const int不算重载;
void fun(int* a) {};
void fun(const int* a) {};
//是重载,这是因为const在参与类型判断的时候只看其右边有没有指针,有的话const起作用,否则不起作用。
//分别是void fun(int* )和void fun(int const* )的重载
打印指针类型
int main()
{ int p = 20;const int* a1 = &p;int* const a2 = &p;int* p_ = &p;cout << typeid(p_).name() << endl;cout << typeid(a1).name() << endl;cout << typeid(a2).name() << endl;return 0;
}
指针和引用
运算符重载
c++运算符重载:使对象的运算表现得和编译器内置类型一样
加法运算符重载
//定义复数类的加法运算符重载
class CComplex
{
public:CComplex(int r=0,int i=0):mreal(r),mimage(i){}//指导编译器实现CComplex类对象的加法操作CComplex operator +(const CComplex &src){return CComplex(this->mreal + src.mreal, this->mimage + src.mimage);}void show(){cout << mreal <<"+" << mimage<<"j"<<endl;}
private:int mreal;int mimage;
};
int main()
{CComplex comp1(10, 20);CComplex comp2(20, 20);//优先调用成员方法运算符+CComplex comp3 = comp1 + comp2; //即comp1.operator(comp2)comp3.show();//优先调用成员方法运算符+CComplex comp4 = comp1 + 20; //即comp1.operator(CComplex(20,0))comp4.show();
}
全局作用域加法运算符重载
CComplex comp5 = 30+comp2;// 全局运算符+ comp5.show();
编译器不知道其需要将30转换成复数类型,报错(没有找到接受“CComplex”类型的全局运算符(或没有可接受的转换))
因为30是常量,不能调用作为复数类的成员方法;并且因为30在左边,编译器不知道将30转换成复数类对象(如int a=10+20,这种也不能遇到+号就转换成复数类对象)
1.编译器做对象运算的时候,优先找对象的运算符重载函数;
2.如果没找到,就在全局作用域(::)中找;
3.如果全局作用域没找到,报错
class CComplex
{
//省略其他
private://在CComplex中定义为友元函数,这样能够访问私有变量friend CComplex operator +(const CComplex& l, const CComplex& r);
};
//全局作用域内定义
//这个是重载了一个全局的+运算符,CComplex comp5 = 30+comp2;
CComplex operator+ (const CComplex& l, const CComplex& r)
{return CComplex(l.mreal + r.mreal, l.mimage + r.mimage);
}
自增运算符重载
//前置++和后置++是单目运算符,通过是否带有形参来区别是前置还是后置运算符//带参数,后置++CComplex operator++(int){CComplex comp = *this;mreal += 1;mimage += 1;return comp;}//不带参数,前置++//对象本身,返回引用,减少内存开销CComplex& operator++(){mreal += 1;mimage+= 1;return *this;}
复合运算符(+=)重载
void operator +=(const CComplex& src){this->mreal += src.mreal;this->mimage += src.mimage;}
输入输出流运算符重载
输出流重载,如实现cout<<comp1<<endl;
因为cout不是CComplex类,所以需要在全局作用域中声明
//同样需要在CComplex类中声明友元函数,以访问成员变量
ostream& operator<<(ostream& out, const CComplex& src)
{out << src.mreal << "+" << src.mimage << "j" << endl;return out;
}istream& operator>>(istream& in, CComplex& src)
{in >> src.mreal >> src.mimage;return in;
}