//安全计数器
//重载运算符(++、--、())
/*#include<iostream>
using namespace std;
class x{
private:
unsigned int value;
public:
x(){value=0;}
void operator++();
void operator--();
unsigned int operator ()();
};
int main()
{
x x1;
int i;
for(i=0;i<5;i++)
{++x1;
cout<<"x1="<<x1()<<endl;}
for(i=0;i<=5;i++)
{ --x1;
cout<<"x1="<<x1()<<endl;}
return 0;
}
void x::operator ++(){ //自增
++value;}
void x::operator --(){ //自减
if(value>0) --value;
else
{cout<<"nell"<<endl;
exit(0); //非常重要!结束这次进程,否则x1.value的值依旧为0再次调用会多输出个0.
}
}
unsigned int x::operator ()(){ //()作用返回数据成员完成对类的读取
return value;}
*/
//重载+、=、++
/*#include<iostream>
using namespace std;
class tricoor{
private:
int x;
int y;
int z;
public:
tricoor(int x1=0,int y1=0,int z1=0){x=x1;y=y1;z=z1;}
tricoor operator +(tricoor a);
tricoor operator =(tricoor a);
tricoor operator ++();
void display();
void assign(int x1,int y1,int z1);
};
tricoor tricoor::operator +(tricoor a)
{
tricoor temp;// 当类中有默认构造函数(可以对类初始化时)在成员函数中可以创建临时的该类对象!!!(如果没有默认构造函数不可以在类的成员函数中使用该类对象)
temp.x=x+a.x;
temp.y=y+a.y;
return temp;}
tricoor tricoor::operator ++()
{++x;++y;++z;
return *this;}
tricoor tricoor::operator =(tricoor a) //赋值
{x=a.x;y=a.y;z=a.z;
return *this;}
void tricoor::assign(int x1,int y1,int z1) //完成对类的写操作
{x=x1;y=y1;z=z1;}
void tricoor::display()
{cout<<"x="<<x<<"y="<<y<<"z="<<z;}
int main()
{
tricoor a(1,2,3),b,c;
a.display();
b.display();
c.display();
for(int i=0;i<5;i++) ++b;
b.display();
c.assign (3,3,3);
c.display ();
c=b=a;
c.display();
return 0;
}*/
/*#include<iostream>
using namespace std;
class TriCoor
{ public:
TriCoor( int mx = 0, int my = 0, int mz = 0 ) { x = mx ; y = my ; z = mz ; }
TriCoor operator + ( TriCoor t )
{ TriCoor temp ;
temp.x = x+t.x ; temp.y = y+t.y ; temp.z = z+t.z ;
return temp ;
}
TriCoor operator = ( TriCoor t ) { x = t.x ; y = t.y ; z = t.z ; return * this ; }
TriCoor operator ++ () { x ++ ; y ++ ; z ++ ; return *this ; }
void show() { cout << x << " , " << y << " , " << z << "\n"; }
void assign( int mx, int my, int mz ) { x = mx; y = my; z = mz; }
private: int x, y, z ;
};
int main()
{ TriCoor a( 1, 2, 3 ), b, c ;
a.show(); b.show(); c.show();
for( int i = 0; i < 5; i ++ ) ++ b; b.show() ;
c.assign( 3, 3, 3 ) ; c = a + b + c ; c.show() ;
c = b = a ; c.show() ;
return 0
} */
//友员函数重载
//(双目运算符加减+、-单目运算符取反-)
/*#include<iostream.h>
class complex{
private:
double a;
double b;
public:
complex(int a1){ a=a1;b=0;}//Complex(int a) { Real = a ; Image = 0 ; }完成对类型转换将int-》complex类
complex(double a1=0,double b1=0){a=a1;b=b1;}//当类中有默认构造函数(可以对类初始化时)在成员函数中可以创建临时的该类对象!!!(如果没有默认构造函数不可以在类的成员函数中使用该类对象)
void display();//void print() const ;常函数不能修改对象的数据成员,仅能调用,可以有效的保护数据(注意const参与函数重载)
friend complex operator+(complex c1,complex c2); // friend Complex operator+ ( const Complex & c1, const Complex & c2 ) ;
//如果形参使用引用则在实参向形参赋值时可以避免调用复制构造函数提高代码的运行效率和准确率因此在传参时使用引用的方式是一个好的习惯。
//在使用引用的时候常常因实际问题而用常引用类型可以避免对数据的更改“const 类型 & 对象名”
friend complex operator-(complex c1,complex c2);// friend Complex operator- ( const Complex & c1, const Complex & c2 ) ;同理
friend complex operator-(complex c1);// friend Complex operator- ( const Complex & c ) ;同理
};
void complex::display(){ //void Complex :: print() const
//{ cout << '(' << Real << " , " << Image << ')' << endl ; }
cout<<"("<<a<<","<<b<<")"<<endl;}
complex operator +(complex c1,complex c2)// friend Complex operator- ( const Complex & c ) ;
{ // { double r = c1.Real + c2.Real ; double i = c1.Image+c2.Image ;
// return Complex ( r, i ) ;}
complex temp(0,0); // 新思路:先计算出数据成员的值再在返回函数中调用构造函数将其转化成类类型。
temp.a=c1.a+c2.a;
temp.b=c1.b+c2.b;
return temp;//先创建一个类的对象,对类的数据成员进行赋值
}
complex operator -(complex c1,complex c2) // Complex operator - ( const Complex & c1, const Complex & c2 )
{ // { double r = c1.Real - c2.Real ; double i = c1.Image - c2.Image ;
complex temp(0,0); // return Complex ( r, i ) ;}同理
temp.a=c1.a-c2.a;
temp.b=c1.b-c2.b;
return temp;
}
complex operator -(complex c1) //Complex operator - ( const Complex & c1, const Complex & c2 )
{ // { double r = c1.Real - c2.Real ; double i = c1.Image - c2.Image ;
complex temp(0,0); //return Complex ( r, i ) ;}
temp.a=-c1.a;
temp.b=-c1.b;
return temp;
}
int main()
{
complex c1(2.5,3.7),c2(4.2,6.5);
complex c;
c=c1-c2;
c.display();
c=25+c2;
c.display();
c=c2+25;
c.display();
c=-c1;
c.display();
return 0;}
*/
//重载a++和++a
/*#include<iostream>
using namespace std;
class increase{
private:
unsigned value; //不要局限于int/double等基本类型会很low
public:
increase(){value=0;}
void display() const; //学会用const更高级
increase operator ++();//前置
increase operator ++(int);//后置
};
increase increase::operator ++ ()
{++value; return *this;} //谁调用返回谁
increase increase::operator ++(int) //int伪参数用于区分前后置
{
increase temp;
temp.value=value++;
return temp;} //经典套路
void increase::display()const{
cout<<value<<endl;
}
int main()
{
increase a,b,n; int i;
for(i=0;i<10;i++) a=n++; //n.operator++();n调用返回n
cout<<"n=";n.display();cout<<"a=";a.display();
for(i=0;i<10;i++) b=++n;
cout<<"n=";n.display();
cout<<"b=";b.display();
return 0;
}*/
//在自定义的类中,运算符重载需要返回类对象的引用。
//如果返回的是类的对象,则在赋值的过程中会调用拷贝构造函数,引起不必要的运算。
//如果返回的是void,则不能进行连续赋值
//在自定义类的对象连续赋值中a=b=c当运算符返回的是类对象的引用时,其过程为b=c调用运算符重载函数b.operator=(c),返回的是b的引用,然后a=b调用运算符重载函数,返回a的引用。(谁调用返回谁)
//当运算符重载函数返回的是类对象时,其过程为b=c先调用运算符重载函数,该函数结束后,由于返回的是类对象,因此在a=b=c这行代码中会创建一个临时对象temp-c,用于接收运算符重载之后结果,此时
//会调用拷贝构造函数temp—c(*this),其中this是运算符重载函数中的。同时a=temp-c调用运算符重载函数然后在a=b=c创建一个临时类对象temp-a,然后调用拷贝构造函数temp-a(*this)然后释放temp-a(析构函数)
//再释放temp-c析构函数
//重载赋值运算符(用于对象数据的复制,必须重载为成员函数)
/*#include<iostream>
#include<cstring>
using namespace std;
class name{
public:
name(char *pn);
name(const name&); //复制构造函数
name &operator =(const& name); //重载赋值运算符
~name();
protected:
char *pname;
int size;
};
name::~name(){
delete []pname;}
name::name(char *pn) //构造函数
{
cout<<"constructing"<<pn<<endl;
pname=new char[strlen(pn)+1];
if(pname!=0)strcpy(pname,pn);
size=strlen(pn);
}
name::name(const name&obj) //因为在堆上产生了空间在复制时就要用深复制
{
cout<<"copying"<<obj.pname<<"into its own blockn";
pname=new char[strlen(obj.pname)+1];
if(pname!=0)strcpy(pname,obj.pname);
size=obj.size;
}
name &name::operator=(const name &obj) //重载赋值运算符函数,为防止溢出和内存空间过大我们采取将原空间删除后重新创建合适大小的空间重新存储
{ //返回值使用引用可以更好地高效率的进行运行不用调用多余的构造函数和析构函数,可以避免错误;参数使用引用是为了在函数中的改变同时引起对象的改变(在没有返回值和赋值操作下)直接建立联系同时在传参是可以不用调用构造函数
delete []pname; //删除原空间
pname=new char[strlen(obj.pname)+1];//创建一个新的大小正合适的空间
if(pname!=0)strcpy(pname,obj.pname);//创建完成后的赋值操作
size=obj.size; //将指示的空间大小同时进行改变
return *this; //有返回值的原因:可以实现连续的赋值连等
}
int main()
{
name obj1("zhangsan"); //调用构造函数
name obj2=obj1; //调用复制构造函数对新建的对象进行初始化区分于重载的赋值构造函数
name obj3("no name"); //调用构造函数
obj3=obj2=obj1; //调用重载赋值运算符函数
return 0; //复制构造函数在对新创建的对象(还未初始化的对象)初始化时调用而赋值运算符的重载函数是在对已有对象(对象的数据成员都有值的)的更改
}*/
//重载运算符([]和())注意:都是二元运算符且都只能用成员函数重载,不能用友员函数重载
/*#include<iostream>
using namespace std;
class vector
{
public:
vector(int n){v=new int [n];size=n;}
~vector(){delete[]v;size=0;} //有new就一定要有delete
int &operator[](int i){return v[i];} //返回元素的引用this->v[i]
//如果没有引用则v[]在返回的时候会创建一个int类型temp临时变量temp再赋给a[]两者之间的关联消失了
//如果返回引用无需产生临时变量a[2]=12等价于(&)v[2]=12
//关键返回引用不用建立临时变量直接等价!!!!!!!!
private:
int *v;
int size;
};
int main(){
vector a(5);
a[2]=12; //返回引用的函数调用作为左值//a.operator[](2)本质想将12赋给v[2],怎么让a[2]与v[2]扯上关系:引用 12赋给a[2]的引用v[2]真实的改变v[2];
cout<<a[2]<<endl; //输出时a[2]再次调用a.operator[](2)此时返回的还是v[2]只不过此时的v[2]有值值为12
return 0;
}*/
//重载运算符(()以一种统一的外观调用函数)
/*#include<iostream>
using namespace std;
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;
cout<<f(5.2,2.5)<<endl; //f.operator()(5.2,2.5)
return 0;
}*/
/*#include <iostream> //比较定义的普通成员函数
using namespace std ;
class F
{ public :
double memfum ( double x , double y ) ;
} ;
double F :: memfum( double x , double y )
{ return x * x + y * y ; }
int main ( )
{ F f ;
cout << f. memfum ( 5.2 , 2.5 ) << endl ;
}*/
//重载流插入和流提取运算符
/*istream 和 ostream 是 C++ 的预定义流类
cin 是 istream 的对象,cout 是 ostream 的对象
运算符 << 由ostream 重载为插入操作,用于输出基本类型数据
运算符 >> 由 istream 重载为提取操作,用于输入基本类型数据
用友元函数重载 << 和 >> ,输出和输入用户自定义的数据类型 */
/*#include<iostream>
#include<cstdlib>
using namespace std;
class vector
{
public:
vector( int size =1 ) ; ~vector() ;
int & operator[] ( int i ) ;
friend ostream & operator << ( ostream & output , vector & ) ; //ostream标准流类
friend istream & operator >> ( istream & input, vector & ) ; //istream标准流类
private :
int * v ; int len ;
};
int main()
{ int k ;
cout << "Input the length of vector A :\n" ; cin >> k ;//使用系统预定义版本(原本的运算效果)
vector A( k ) ;
cout << "Input the elements of vector A :\n" ; cin >> A ;//使用重载版本
cout << "Output the elements of vector A :\n" ;
cout << A ;
return 0;
}
vector::vector( int size )
{ if (size <= 0 || size > 100 )
{ cout << "The size of " << size << " is null !\n" ; exit( 0 ) ; }
v = new int[ size ] ; len = size ;
}
vector :: ~vector() { delete[] v ; len = 0 ; }
int & vector :: operator [] ( int i )
{ if( i >=0 && i < len ) return v[ i ] ;
cout << "The subscript " << i << " is outside !\n" ; exit( 0 ) ;
}
ostream & operator << ( ostream & output, vector & ary ) // & output是cout的别名 !!!返回流类引用用于连续的输入和输出
{ for(int i = 0 ; i < ary.len ; i ++ ) output << ary[ i ] << " " ; //使用重载版本
output << endl ;
return output ;
}
istream & operator >> ( istream & input, vector & ary ) //& input是cin的别名 !!!返回流类引用用于连续的输入和输出
{ for( int i = 0 ; i < ary.len ; i ++ ) input >> ary[ i ] ; //使用重载版本
return input ;
}*/
//类类型转换
/*数据类型转换在程序编译时或在程序运行实现
基本类型 ←→ 基本类型
基本类型 ←→ 类类型
类类型 ←→ 类类型
类对象的类型转换可由两种方式说明:
构造函数 转换函数
称为用户定义的类型转换或类类型转换,有隐式调用和显式调用方式*/
//1.构造函数进行类类型转换
/*当类 ClassX 具有以下形式的构造函数:
ClassX :: ClassX ( arg ,arg1 = E1 ,…, argn = En ) ;
说明了一种从参数 arg 的类型到该类类型的转换*/
/*class X
{ // ……
public :
X ( int ) ;
X ( const char * , int = 0 ) ;
};
void f ( X arg ) ;
:
X a = X( 1 ) ; // a = 1 //调用构造函数 X ( int ) 把 1 转换为类类型 X 后赋给对象 a也称 X ( 1 ) 为 X 类的类型常量
X b = "Jessie" ; // b = X ( "Jessie" , 0 )//调用构造函数X ( const char * , int = 0 ) 把字符串转换为类类型 X 后赋给对象 b
a = 2 ; // a = X ( 2 )//隐式调用构造函数 X ( int ) 把 2 转换为类类型 X 后赋给对象
f ( 3 ) ; // f ( X ( 3 ) )//隐式调用构造函数 X ( int ) 对实参作类类型转换,然后做参数结合
f ( 10 , 20 ) ; // error//当找不到匹配的构造函数时转换失败
//隐式类型转换由系统自动完成
//7.4.2 类型转换函数
/*带参数的构造函数不能把一个类类型转换成基本类型
类类型转换函数是一种特殊的成员函数,提供类对象之间
显式类型转换的机制*/
/*语法形式:
X :: operator T ( )
{ ……
return T 类型的对象
}
功能:将类型 X 的对象转换为类型 T 的对象T 可以是预定义类型,也可以是用户定义类型
函数没有参数,没有返回类型,但必须有一条 return 语句,返回 T 类型的对象
该函数只能为成员函数,不能为友元*/
/*class X
{ ……
public :
operator int ( ) ;
……
} ;
void f ( X a ) //a 是一个类对象,它们都用类型转换函数作类型转换X :: operator int ()
{ int i = int ( a ) ;
i = ( int ) a ;
i = a ;
}
*/
/*类型转换函数有两种使用方式:
隐式使用 i = a ;
显式使用 i = a . operator int ( ) // int ( a ) ( int ) a
使用不同函数作类型转换函数:
int i = a ; // 用类型转换函数进行转换
X i = a ; // 用构造函数进行转换
*/
//构造函数进行类型转化是将基本类型向类类型转化
//类型转化函数可以实现类类型向基本类型和其他类类型的转变
C++运算符重载心得
最新推荐文章于 2024-07-28 21:35:11 发布