动态网站制作指南 [  QQ表情  ]
[ 投票调查 ]
[ 企业邮箱 ]
[ 网站空间 ]
网络编程 | 站长之家 | 网页制作 | 图形图象 | 操作系统 | 冲浪宝典 | 软件教学 | 网络办公 | 邮件系统 | 网络安全 | 认证考试 | 系统进程
ASP源码 | .Net源码 | PHP源码 | JSP源码 | JAVA源码 | CGI源码 | VB源码 | C++源码 | Delphi源码 | PB源码 | VF源码 | 汇编 | 服务器
Firefox | IE | Maxthon | 迅雷 | 电驴 | BitComet | FlashGet | QQ | QQ空间 | Vista | 输入法 | Ghost | Word | Excel | wps | Powerpoint
asp | .net | php | jsp | Sql | c# | Ajax | xml | Dreamweaver | FrontPages | Javascript | css | photoshop | fireworks | Flash | Cad | Discuz!
当前位置 > 网站建设学院 > 网络编程 > C/C++教程
Tag:注入,存储过程,分页,安全,优化,xmlhttp,fso,jmail,application,session,防盗链,stream,无组件,组件,md5,乱码,缓存,加密,验证码,算法,cookies,ubb,正则表达式,水印,索引,日志,压缩,base64,url重写,上传,控件,Web.config,JDBC,函数,内存,PDF,迁移,结构,破解,编译,配置,进程,分词,IIS,Apache,Tomcat,phpmyadmin,Gzip,触发器,socket
网络编程:ASP教程,ASP.NET教程,PHP教程,JSP教程,C#教程,数据库,XML教程,Ajax,Java,Perl,Shell,VB教程,Delphi,C/C++教程,软件工程,J2EE/J2ME,移动开发
文章搜索服务
邮件订阅
输入你的邮件地址,
你将不会错过任何关于:
[ C/C++教程 ]的信息

本月文章推荐
.用C语言描述数据结构.
.《TVS2.0应用实录》004:Togethe.
.想成为嵌入式程序员应知道的0x10.
.《c语言程序设计》第七章:结构与.
.C与脚本的混合编程.
.用BCB5的打包程序打包BCB6.
.在CB中实现流类的版本控制.
.C++箴言:理解隐式接口和编译期多.
.钟表.
.C++中对浮点数的格式化显示.
.C++箴言:绝不在构造或析构期调用.
.又一个贪吃蛇.
.单元测试工具C++ Test简介.
.C++ 基类和派生类.
.CRichEditCtrl实现MSN/QQ动画表情.
.C++箴言:视类设计为类型设计.
.在CB5中使用ADO数据库编程.
.了解C++异常处理的系统开支.
.在C语言中以编程的方式获取函数名.
.C++的底层机制.

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

发表日期:2008-3-8 |


  为什么需要转换运算符?  大家知道对于内置类型的数据我们可以通过强制转换符的使用来转换数据,例如(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语句。     在很多情况下,类的强转换运算符还可以作为类对象加运算重载函数使用,尽管他们的意义并不相同,下面的例子,就是利用转换运算符,将两个类对象转换成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);完全相同。

  运行结果如下图示(注重观察内存地址,观察构造与析构过程,执行过程图中有解释): 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"); 
}   按照C++对无名对象的约定,Test b=Test(99);C++是会按照Test b(99);来处理的,可是由于转换运算符的加入,导致这一规律被破坏,系统会“错误的”认为你是要给对象赋值,所以系统首先利用Test(99)创建一个临时对象用于赋值过程使用,可是恰恰系统又没有使用自动提供的赋值运算重载函数去处理,因为发现b对象并未构造,转而又不得不将开始原本用于赋值而创建的临时对象再次的强转换为int类型,提供给b对象进行构造,可见中间的创建临时对象和载入转换运算符函数的过程完全是多余,读者对此例要认真解读,充分理解。

  运行结果如下图所示(运行过程的解释见图): 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"); 
}   运行过程见下图。 C++运算符重载转换运算符   从图中我们可以清楚的看到,不必要的运算过程被执行,导致开销增大,读者在理解此例的时候要格外小心!

现在总结一下转换运算符的优点与缺点:

  优点:在不提供带有类对象参数的运算符重载函数的情况下,转换运算符重载函数可以将类对象转换成需要的类型,然后进行运算,最后在构造成类对象,这一点和类的运算符重载函数有相同的功效。(例2就是这种情况)

  缺点:假如一个类只有转换运算符重载函数,而没有真正意义上运算符重载函数,当用转换运算符重载函数替代运算符重载函数,进行工作的时候,就会让程序的可读性降低,歪曲了运算符操作的真正含义。(例2中的c=a+b;//隐式转换,就是例子,事实上a+b的作用只是对返回的整型数据进行了加运算,而对象赋值的操作是系统隐式的帮大家转换成了c=Test(a+b)。)   最后我们来说一下,多路径转换的多义性问题,多义性问题一直是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类的转换构造函数处理,所以,显式的告诉计算机应该如何处理数据,通常可以解决多义性问题。
上一篇:从源程序看原理:突破防火墙入侵内网 人气:641
下一篇:C++的iostream标准库介绍(3) 人气:855
浏览全部C/C++的内容 Dreamweaver插件下载 常用网页广告代码全集
  最新网站源码 最新软件下载
2008-12-4 PhpCMS2008 bulid 081203 简体中
2008-12-4 Menalto Gallery v1.5.10 多国语
2008-12-4 Phpcms2008 bulid 081203 简体中
2008-12-4 乘风多用户计数器 v3.92 (Acc)
2008-12-4 乘风多用户计数器 v3.92 (Sql)
2008-12-4 BBSxp 2008 8.0.5 SP2 Build 081
2008-12-4 ASBLOG v2.5 bulid 081118(1201)
2008-12-4 非零坊幽默短信 v3.4
2008-12-4 红茶巴士(公交)查询系统 v3.0
2008-11-29 Tencent Traveler 4.4
2008-11-29 龙卷风网络收音机 v3.0.0.0
2008-11-29 Intel Chipset Software Install
2008-11-29 TweakVI 1.0 Build 1100
2008-11-29 Opera 9.62 Build 10469
2008-11-29 MPlayer WW编译版 SVN-r28044(20
2008-11-29 NetTools网络工具v1.0.0破解版
2008-11-29 3DGallery三维体验1.1破解版
2008-11-29 SecretBook保密本v1.0破解版
  发表评论
姓 名: 验证码:
内 容:
站长工具:网站收录查询 | Google PR查询 | ALEXA排名查询 | CSS在线编辑器 | OPEN参数生成器 | 弹出式窗口代码产生器 | 密码登录生成器 | 在线按钮生成器 | Meta标签生成器 | 多色彩特效字代码生成器 | 网页代码调试器 | 在线FTP登陆 | Flash取色器 | 配色代码对照表 | 配色辞典 | CSS生成器 | 广告代码 | 框架网页代码生成器 | js/vbs加密 | md5加密 | 进制转换 | UTF-8 转换工具 | 在线调色板 | Html转换js | Html转换asp | Html转换php | Html转换perl
实用工具:汉字翻译拼音 | 拼音字典 | 符号对照表 | 个税计算 | 实时汇率查询换算 | 经典小工具 | 汉字简繁转换 | 普通单位换算 | 公制单位换算 | 生辰老黄历 | 国内电话区号 | 国家代码与域名缩写 | 文字加密解密 | 元素周期表 | 健康查询 | 世界时间 | 万年历 | 二十四节气 | 汉字横竖排版 | 手机号码查询 | 计算器 | ip搜索
业务联系 | 广告刊登 | 频道合作 | 投稿荐稿 | 联系方式 | 加入收藏 | RSS订阅
Copyright © 2000-2009 www.knowsky.com All rights reserved | 沪ICP备05001343号
ホームページ制作 不動産検索システム 求人情報
防水工事·改修工事 フットサル大会 探偵
SEO対策 中国語教室 ホームページ作成