}
6、友元运算符函数和成员运算符函数有什么不同?哪些运算符只能用友元?哪些运算符只能用成员函数?哪些两者均可?
解:
不同点:运算符函数如果是类的成员函数,则它具有一个隐含的this指针,this所指对象就成为第一个操作数。即用成员运算符函数表示一个双目运算符,该成员运算符函数有一个参数,表示第二个操作数;用成员运算符函数表示一个单目运算符,该成员运算符函数有没有参数。运算符运算符函数如果是类的友元函数,则它没有this指针。即用友元运算符函数表示一个双目运算符,该函数有两个参数;用友元运算符函数表示一个单目运算符,该函数有一个参数。友元运算符函数总是比成员运算符函数多一个函数参数。
只能用友元函数:第一个操作数不是类的操作对象。
只能用成员函数:这些运算符是:=(赋值)、[](下标)、()(函数调用)、->(通过指针访问成员),以及所有的类型转换运算符。
两者均可:在多数情况下,将运算符重载为类的成员函数和类的友元函数都是可以的。
在多数情况下,将运算符重载为类的成员函数和类的友元函数都是可以的。但成员函数运算符与友元函数运算符也具有各自的一些特点:
(1) 一般情况下,单目运算符最好重载为类的成员函数;双目运算符则最好重载为类的友元函数。
(2) 以下一些双目运算符不能重载为类的友元函数:=、()、[]、->。
(3) 类型转换函数只能定义为一个类的成员函数而不能定义为类的友元函数。
(4) 若一个运算符的操作需要修改对象的状态,选择重载为成员函数较好。
(5) 若运算符所需的操作数(尤其是第一个操作数)希望有隐式类型转换,则只能选用友元函数。
(6) 当运算符函数是一个成员函数时,最左边的操作数(或者只有最左边的操作数)必须是运算符类的一个类对象(或者是对该类对象的引用)。如果左边的操作数必须是一个不同类的对象,或者是一个内部类型的对象,该运算符函数必须作为一个友元函数来实现。
(7) 当需要重载运算符具有可交换性时,选择重载为友元函数。
7、判断对错,说明理由:
(1)重载函数和运算符都是是用静态联编实现的。因为:C++在编译时常采用“名字压延“的方法来区分重载函数。名字压延是在编译器“看”到函数后改变函数名。亦即C++把重载函数的本名和参数结合起来创造函数的新名字,在程序中每一处说明原型、定义和调用这些函数的地方,C++均用压延名字来替代。例如:
有以下两个函数原型:
int myAns(float x,int j);
int myAns(int i,char c);
并用以下语句调用它们:
exam1=myAns(15,3,15);
exam2=myAns(45,’a’);
则在编译完成之前,C++也许会将函数名改变成如下形式:
int myAnsFLTINT(float x,int j);
int myAnsINTCHAR(int I,char c);
同时C++也会在函数调用的地方改变名字,如:
exam1=myansFLTINT(15,3,15);
exam2=myAnsINTCHAR(45,’a’);
解:对。
(2)程序段:
complex complex::operator +(complex c2) //重载函数实现
{
complex c;
c.real=c2.real+real;
c.imag=c2.imag+imag;
return complex(c.real,c.imag);
}
中的语句:
return complex(c.real,c.imag);
可以用语句return c;
替换。因为在函数返回的时候,可以返回临时对象,也可以直接用类的构造函数来生成一个无名临时对象并返回它,而不对该对象命名。
解:对。
(3)要实现动态联编,派生类中的虚函数的参数类型可以与虚函数的原型不同。
解:错。这会导致派生类的虚函数不能覆盖基类的虚函数,也就不能实现动态联编。
8、存在这样的抽象类吗?该类定义中并没有定义纯虚函数。
解:存在。原因有二,
1,纯虚函数只需声明,不必给出定义。2,抽象类派生出新的类后,如果派生类没有给出全部纯虚函数的实现,这时的派生类仍是抽象类。
9、找出下面程序运行结果错误的原因(未按++运算符的要求做),并改正。
#include
class coord{
int x,y;
public:
coord(int i=0,int j=0);
void print();
friend coord operator++(coord &op);//
};
coord::coord(int i,int j)
{x=i;y=j;}
void coord::print()
{cout<<" x:"<coord operator ++(coord &op)//
{ ++op.x;
++op.y;
return op;
}
main()
{ coord ob(10,20);
ob.print();
++ob;//
ob.print();
operator++(ob);//
ob.print();
return 0;
}
错误原因:值传递不会改变原数的值。
10、附加题:
(1)写出下列程序的运行结果,并分析该程序中关于“+”的运算符重载可以用成员函数实现吗?为什么?
#include
class AB
{
int a,b;
public:
AB(int x=0,int y=0)
{a=x;b=y;}
friend AB operator+(AB ob,int x);//友元函数
friend AB operator+(int x,AB ob);//友元函数
void print();
};
AB operator+ (AB ob,int x)//定义友元运算符函数
{ AB temp;
temp.a=ob.a+x;
temp.b=ob.b+x;
return temp;
}
AB operator+(int x,AB ob) //定义友元运算符函数
{ AB temp;
temp.a=x+ob.a;
temp.b=x+ob.b;
return temp;
}
void AB::print()
{cout<<"a="<};
class perimenter:public circle{
public:
void show()//
{cout<<"perimenter is "<<2*3.14*r<};
void main()
{ circle *ptr;
area ob1;
perimenter ob2;
ob1.setr(10);
ob2.setr(10);
ptr=&ob1;
ptr->show();
ptr=&ob2;
ptr->show();
}
解:运行结果:
area is 314
perimenter is 62.8
Press any key to continue
virtual void show()=0的含义是声明show为纯虚函数(即抽象函数),为子类提供一个统一的接口。
(3)写出下列程序的运行结果,并说明其结果为什么不是:
In Base class,int x=2
In Base class,int x=3
In Sube class,double x=2.0
In Sube class,double x=3.5
=====================================
#include
using namespace std;
class Base{
public:
virtual void fn(int x){ cout<<"In Base class, int x = "<};
class Sub : public Base{
public:
virtual void fn(double x){ cout<<"In Sub class, double x = "<};
void test(Base& b){
b.fn(2);
b.fn(3.5);
}
int main()
{
Base a;
test(a);
Sub b;
test(b);
}
解:运行结果:
In Base class, int x = 2
In Base class, int x = 3
In Base class, int x = 2
In Base class, int x = 3
Press any key to continue
因为派生类的fn函数参数类型为double型,与基类类型不同,导致派生类的虚函数不能覆盖基类的虚函数,从而调用时均调用的是基类的fn函数
所以结果不是
In Base class,int x=2
In Base class,int x=3
In Sube class,double x=2.0
In Sube class,double x=3.5
改为以下
#include
using namespace std;
class Base{
public:
virtual void fn(double x){ cout<<"In Base class, int x = "<<(int)x<<"\n"; }
};
class Sub : public Base{
public:
virtual void fn(double x){ cout<<"In Sub class, double x = "<};
void test(Base& b){
b.fn(2);
b.fn(3.5);
}
int main()
{
Base a;
test(a);
Sub b;
test(b);
}
In Base class, int x = 2
In Base class, int x = 3
In Sub class, double x = 2
In Sub class, double x = 3.5
Press any key to continue