在前面我们学习了关于类的一些基本使用,下面我们更深入的学习使用类。这里包含了下面几个内容:
1:操作符重载
2:友员
3:类的转换
操作符重载:使我们对类型使用+、-等常用操作符。要重载操作符,需使用称为运算符函数的特殊函数,它的形式如下:
operator op(argument-list) ; op 可以是+、-、*、/等操作符,argument-list 是参数列表
下面创建一个两个时间相加的+操作符:
#include<iostream>
using namespace std ;
class Time{
private :
int hour , minute , second ;
public :
Time(int hour , int minute , int second) ;
Time() {} //默认构造函数
Time operator+(const Time &t) const ;
void show()const ;
} ;
int main(){
Time t1(3 , 20 , 30) ;
Time t2(4 , 30 , 10) ;
cout << "t1 : \n" ;
t1.show() ;
cout << "t2 : \n" ;
t2.show() ;
Time t3 = t1 + t2 ;
cout << "t3 : \n" ;
t3.show() ;
return 0 ;
}
Time::Time(int hour , int minute , int second){
this->hour = hour ;
this->minute = minute ;
this->second = second ;
}
Time Time::operator+(const Time &t) const {
Time sum ; //使用默认构造函数
sum.second = second + t.second ;
sum.minute = minute + t.minute + sum.second/60 ;
sum.hour = hour + t.hour + sum.minute/60 ;
sum.second %= 60 ;
sum.minute %= 60 ;
sum.hour %= 24 ;
return sum ;
}
void Time::show()const {
cout << "hour : " << hour << " minute : "
<< minute << " second : " << second << endl ;
}
Time t3 = t1 + t2 ; 使用重载+操作符 ,运算符右边的值是作为参数传递来的, Time t3 = t1.operator+(t2) ; 这样使用也可以
重载运算符不是一定是成员函数,也可以是非成员函数,但必须至少有一个操作数是用户定义的类型。如:
#include<iostream> using namespace std ;
class Time{ private : int hour , minute , second ; public : Time(int hour , int minute , int second) ; Time() {} //默认构造函数 Time operator+(const Time &t) const ; //友元函数 在函数中可以直接使用该类的私有成员 friend Time operator+(int h , const Time &t ) ; friend Time operator+(const Time &t , int h ) ; void show()const ; } ; int main(){ Time t1(3 , 20 , 30) ; Time t2(4 , 30 , 10) ; cout << "t1 : \n" ; t1.show() ; cout << "t2 : \n" ; t2.show() ; //重载操作符作为成员函数时,对象必须在操作符的左边 Time t3 = t1 + t2 ; cout << "t3 : \n" ; t3.show() ; //重载操作符作为非成员函数时,第一个参数在左边,第二个在右边 Time t4 = t1 + 5 ; cout << "t4 : \n" ; t4.show() ; Time t5 = 5 + t1 ; cout << "t5 : \n" ; t5.show() ; return 0 ; } Time::Time(int hour , int minute , int second){ this->hour = hour ; this->minute = minute ; this->second = second ; } Time Time::operator+(const Time &t) const { Time sum ; //使用默认构造函数 sum.second = second + t.second ; sum.minute = minute + t.minute + sum.second/60 ; sum.hour = hour + t.hour + sum.minute/60 ; sum.second %= 60 ; sum.minute %= 60 ; sum.hour %= 24 ; return sum ; } void Time::show()const { cout << "hour : " << hour << " minute : " << minute << " second : " << second << endl ; } //非成员函数 Time operator+(int h , const Time &t ) { Time sum ; sum.hour = (sum.hour + h)%24 ; return sum ; } Time operator+(const Time &t , int h ) { Time sum ; sum.hour = (sum.hour + h)%24 ; return sum ; }
操作符重载的使用形式都同+操作符重载差不多,根据操作符的实际意义来判断返回值。
友元:c++控制对类对象私有成员的访问,外界只能通过公有方法来访问,若外界也想使用类对象的私有成员,则我们可以将他们设置为类的友元,友元可以访问类对象的私有成员。
友元有三种:
友元函数:将函数设置为类的友元,则在函数中可以访问类的所有成员(包含私有成员)。
友元类 :将类person设置为类Time的友元,则类person的成员函数可以访问类Time的所有成员(包含私有成员)。
友元成员函数:将类person的成员函数setPerson()成员函数设置为类Time的友元,则在成员函数setPerson中可以访问类Time的所有成员(包含私有成员)。
创建友元函数:将函数的声明放在类的声明中,前面加关键字friend,如:
friend Time operator+(int h , const Time &t ) ;
虽然,函数是在类声明中声明的,但它不是成员函数,虽然不是成员函数,但它与成员函数有相同的访问权限。
编写函数定义时,它不是成员函数,不用在Time::限定符,另外,不用再定义总是用friend关键字。
Time operator+(int h , const Time &t ) {
Time sum ;
sum.hour = (sum.hour + h)%24 ;
return sum ;
}
大部分重载运算符既可以用成员函数实现,也可以使用非成员函数实现,非成员函数应该是友元函数,否则不能访问类的私有数据,成员函数的第一个操作数是用this隐性传递的,非成员函数的所有操作数都是函数的参数,操作数的位置是根据参数的位置来定的。
友元类:
#include<iostream>
using namespace std ;
class Ta ;
class Tc {
public :
/*class Ta在class Tc之前声明,可以使用Ta类名,不能使用类Ta的数据成员和成员函数,
因为编译器不知道,如果该函数在这里实现就会出错,不知道ta.a
*/
void changeA(Ta &ta) ;
} ;
class Ta {
int a ;
public :
friend class Tb ; //友元类 在这里也声明了Tb,Ta知道了类名Tb
friend void Tc::changeA(Ta &ta) ; //友元成员函数 因为Tc>声明在Ta之前,这里可以使用Tc::changeA(Ta &ta); 函数声明
Ta(int i) {
a = i ;
}
int getA(){
return a ;
}
};
class Tb {
public :
void changeA(Ta &ta) {
ta.a += 10 ; //可以访问Ta的私有成员
}
} ;
void Tc::changeA(Ta &ta) { //不能放在Tc类中实现,因为不能使用ta.a
ta.a += 20 ;
}
int main(){
Ta ta(10) ;
cout << "before : a : " << ta.getA() << endl ;
Tb tb ;
tb.changeA(ta) ;
cout << "now : a : " << ta.getA() << endl ;
return 0 ;
}
要先声明,才能够使用。因为Tc类中在Ta声明之前就使用了Ta类名,则我们应该使用class Ta声明Ta类名,因为Ta的成员还没有声明,所以在Tc类中不能使用Ta的数据成员ta.a, 这个我们应该好好理解下。
类的自动转换和强制转换:
浙公网安备 33010602011771号