C++运算符重载转换运算符
当前位置:以往代写 > C/C++ 教程 >C++运算符重载转换运算符
2019-06-13

C++运算符重载转换运算符

C++运算符重载转换运算符

副标题#e#

为什么需要转换运算符?

各人知道对付内置范例的数据我们可以通过强制转换符的利用来转换数据,譬喻(int)2.1f;自界说类也是范例,那么自界说类的工具在许多环境下也需要支持此操纵,C++提供了转换运算符重载函数,它使得自界说类工具的强转换成为大概。

转换运算符的生命方法较量出格,要领如下:

operator 类名();

转换运算符的重载函数是没有返回范例的,它和类的结构函数,析构函数一样是不遵循函数有返回范例的划定的,他们都没有返回值。

下面我看一个例子,看看它是如何事情的:

//例1

//措施作者:管宁
//站点:www.cndev-lab.com
//所有稿件均有版权,如要转载,请务必著名出处和作者
#include <iostream>
using namespace std;
class Test
{
public:
Test(int a = 0)
{
cout<<this<<":"<<"载入结构函数!"<<a<<endl;
Test::a = a;
}
Test(Test &temp)
{
cout<<"载入拷贝结构函数!"<<endl;
Test::a = temp.a;
}
~Test()
{
cout<<this<<":"<<"载入析构函数!"<<this->a<<endl;
cin.get();
}
operator int()//转换运算符
{
cout<<this<<":"<<"载入转换运算符函数!"<<this->a<<endl;
return Test::a;
}
public:
int a;
};
int main()
{
Test b(99);
cout<<"b的内存地点"<<&b<<endl;
cout<<(int)b<<endl;//强转换
system("pause");
}

在例子中我们操作转换运算符将Test类的工具强转换成了int范例并输出,留意调查转换运算符函数的运行状态,发明并没有发生姑且工具,证明白它与普通函数并不沟通,固然它带有return语句。


#p#副标题#e#

在许多环境下,类的强转换运算符还可以作为类工具加运算重载函数利用,尽量他们的意义并不沟通,下面的例子,就是操作转换运算符,将两个类工具转换成int后,相加并建设姑且类工具,后再赋给另一个工具。

代码如下:

//例2

//措施作者:管宁
//站点:www.cndev-lab.com
//所有稿件均有版权,如要转载,请务必著名出处和作者
#include <iostream>
using namespace std;
class Test
{
public:
Test(int a = 0)
{
cout<<this<<":"<<"载入结构函数!"<<a<<endl;
Test::a = a;
}
Test(Test &temp)
{
cout<<"载入拷贝结构函数!"<<endl;
Test::a = temp.a;
}
~Test()
{
cout<<this<<":"<<"载入析构函数!"<<this->a<<endl;
cin.get();
}
operator int()
{
cout<<this<<":"<<"载入转换运算符函数的内存地点:"<<this->a<<endl;
return Test::a;
}
public:
int a;
};
int main()
{
Test a(100),b(100),c;
cout<<"a的内存地点"<<&a<<" | b的内存地点"<<&b<<endl;
c=Test((int)a+(int)b);//显示式转换
//c=a+b;//隐式转换
cout<<"c的内存地点"<<&c<<endl;
cout<<c.a<<endl;
system("pause");
}

代码中的c=a+b;属于隐式转换,它的实现进程与c=Test((int)a+(int)b);完全沟通。

#p#副标题#e#

运行功效如下图示(留意调查内存地点,调查结构与析构进程,执行进程图中有表明):

C++运算符重载转换运算符

当一个类含有转换运算符重载函数的时候,有时候会粉碎C++原有法则,导致运算效率低落,这一点不得不留意。

示譬喻下:

//例3

//措施作者:管宁
//站点:www.cndev-lab.com
//所有稿件均有版权,如要转载,请务必著名出处和作者
#include <iostream>
using namespace std;
class Test
{
public:
Test(int a = 0)
{
cout<<this<<":"<<"载入结构函数!"<<a<<endl;
Test::a = a;
}
Test(Test &temp)
{
cout<<"载入拷贝结构函数!"<<endl;
Test::a = temp.a;
}
~Test()
{
cout<<this<<":"<<"载入析构函数!"<<this->a<<endl;
cin.get();
}
operator int()//转换运算符,去掉则不会挪用
{
cout<<this<<":"<<"载入转换运算符函数的内存地点:"<<this->a<<endl;
return Test::a;
}
public:
int a;
};
int main()
{
Test b=Test(99);//留意这里
cout<<"b的内存地点"<<&b<<endl;
cout<<b.a<<endl;
system("pause");
}

#p#分页标题#e#

凭据C++对无名工具的约定,Test b=Test(99);C++是会凭据Test b(99);来处理惩罚的,但是由于转换运算符的插手,导致这一纪律被粉碎,系统会“错误的”认为你是要给工具赋值,所以系统首先操作Test(99)建设一个姑且工具用于赋值进程利用,但是恰恰系统又没有利用自动提供的赋值运算重载函数去处理惩罚,因为发明b工具并未结构,转而又不得不将开始原本用于赋值而建设的姑且工具再次的强转换为int范例,提供应b工具举办结构,可见中间的建设姑且工具和载入转换运算符函数的进程完全是多余,读者对此例要当真解读,充实领略。

#p#副标题#e#

运行功效如下图所示(运行进程的表明见图):

C++运算符重载转换运算符

由于类的转换运算符与类的运算符重载函数,在某些处所上利用的时候,有成果相似的处所,假如两者都存在于类中,那么固然运行功效正确,但其运行进程会呈现一些意向不到的步调,导致措施运行效率低落。

下面的例子就是这个环境,代码如下:

//例4

//措施作者:管宁
//站点:www.cndev-lab.com
//所有稿件均有版权,如要转载,请务必著名出处和作者
#include <iostream>
using namespace std;
class Test
{
public:
Test(int a = 0)
{
cout<<this<<":"<<"载入结构函数!"<<a<<endl;
Test::a = a;
}
Test(Test &temp)
{
cout<<"载入拷贝结构函数!"<<endl;
Test::a = temp.a;
}
~Test()
{
cout<<this<<":"<<"载入析构函数!"<<this->a<<endl;
cin.get();
}
Test operator +(Test& temp2)
{
cout<<this<<"|"<<&temp2<<"载入加运算符重载函数!"<<endl;
Test result(this->a+temp2.a);
return result;
}
operator int()
{
cout<<this<<":"<<"载入转换运算符函数的内存地点:"<<this->a<<endl;
return Test::a;
}
public:
int a;
};
int main()
{
Test a(100),b(100);
cout<<"a的内存地点:"<<&a<<" | b的内存地点:"<<&b<<endl;
Test c=a+b;
cout<<"c的内存地点:"<<&c<<endl;
cout<<c.a<<endl;
system("pause");
}

运行进程见下图。

#p#副标题#e#

C++运算符重载转换运算符

从图中我们可以清晰的看到,不须要的运算进程被执行,导致开销增大,读者在领略此例的时候要分外小心!

此刻总结一下转换运算符的利益与缺点:

利益:在不提供带有类工具参数的运算符重载函数的环境下,转换运算符重载函数可以将类工具转换成需要的范例,然后举办运算,最后在结构成类工具,这一点和类的运算符重载函数有沟通的功能。(例2就是这种环境)

缺点:假如一个类只有转换运算符重载函数,而没有真正意义上运算符重载函数,当用转换运算符重载函数替代运算符重载函数,举办事情的时候,就会让措施的可读性低落,歪曲了运算符操纵的真正寄义。(例2中的c=a+b;//隐式转换,就是例子,事实上a+b的浸染只是对返回的整型数据举办了加运算,而工具赋值的操纵是系统隐式的帮各人转换成了c=Test(a+b)。)

#p#分页标题#e#

最后我们来说一下,多路径转换的多义性问题,多义性问题一直是C++编程中容易忽视的问题,但它简直是不容小视,当问题埋没起来的时候你不会觉察,一旦触发贫苦就来了。

类的转换结构函数与类的转换运算符重载函数是互逆的。(例3中的Test(int a = 0)是将int范例的数据转换结构成Test类工具,而operator int()则是将Test类工具转换成int范例数据)

可是当他们是呈此刻两个差异的类中,对付一个类工具转换来说,同时拥有两种近似的转换途径的时候,多义性的问题就袒暴露来,导致编译堕落。

下例就是这个状态:

//措施作者:管宁
//站点:www.cndev-lab.com
//所有稿件均有版权,如要转载,请务必著名出处和作者
#include <iostream>
using namespace std;
class B;
class A
{
public:
A(B &);//转换结构函数,他的浸染是用B类工具结构A类工具
void Edita(int temp)
{
A::a=temp;
}
public:
int a;
};
class B
{
public:
B(int a=0)
{
B::a=a;
}
int Ra()
{
return B::a;
}
operator A()//转换运算符重载函数,他的浸染则是将B类工具转换成A类工具
{
return *this;
}
protected:
int a;
};
A::A(B &temp)
{
cout<<this<<"|"<<&temp<<endl;
A::a=temp.Ra();
}
void tp(A temp)
{

}
int main()
{
B bt(100);
A at=A(bt);
//tp(bt);//错误,多义性问题,系统不知道如何选择,是选择A(B &)转化结构好呢?照旧选择B::operator A()举办转换好呢?
tp(A::A(bt));//显示的处理惩罚可以消除多义性问题
system("pause");
}

代码中的A at=A(bt);运行正常,因为系统发明工具at还未结构,所以优先选取了A类的转换结构函数处理惩罚了,没有发生二义性问题。

可是代码中的tp(bt);编译错误,这是因为函数tp的参数要求的是一个A类工具,而我们给他的则是一个B类工具,而在A类与B类中都有一个雷同的操纵,可以将B类工具转换成A类工具,系统不知道是选取A类的转换结构函数举办结构处理惩罚,照旧选择B类中的转换运算标记重载函数处理惩罚,系统拒绝从他们两其中选一个,所以编译错误。

我们修改tp(bt)为tp(A::A(bt));编译正常,因为我们显式的明晰的汇报系统应该利用A类的转换结构函数处理惩罚,所以,显式的汇报计较机应该如那里理惩罚数据,凡是可以办理多义性问题。

    关键字:

在线提交作业