C++中的operator主要有两个作用,一是操作符的重载,一是自定义对象类型的隐式转换。对于操作符的重载,许多人都不陌生,但是估计不少人都不太熟悉operator的第二种用法,即自定义对象类型的隐式转换,我们下面就用以下这个小例子温故一下这两种用法:

 #include <iostream>
#include <sstream>
using namespace std; class FuncObj
{
public:
FuncObj(int n): _n(n) {
cout << "constructor" << endl;
} bool operator()(int v) {
cout << "operator overload" << endl;
return v > _n;
} operator string() {
cout << "type convert" << endl;
stringstream sstr;
sstr << _n;
return sstr.str();
} int _n;
}; int main()
{
FuncObj obj();
if (obj())
cout << "11 greater than 10" << endl; string str(obj);
cout << str << endl;
}

第12行是操作符重载,重载()使得该对象成为一个函数对象,即该对象有类似函数的功能,在很多场合下可以当成函数指针使用,在STL的很多算法模板里广泛使用。FuncObj用过操作符重载可以判断传入的参数是否大于一个预先设定好的值(在构造函数里指定),见代码的29~31行。

17行的定义表名FuncObj对象可以隐身转换成string,这就是operator的第二个用法,使用方法见代码的33~34行。注意在函数声明时,operator关键词出现在返回类型的前面,区别与操作符重载时的用法。

上述代码的输出:

constructor
operator overload
greater than
type convert

顺便说点题外话,第33行把FuncObj类型的对象传入string的构造函数,是用了c++构造函数的隐式类型转换特性,虽然string类并没有显式定义参数为FuncObj的构造函数,但因为其可以隐式转换为string,所以语法上都是合法的。构造函数的隐式类型转换,是使用一个其他的类型构造当前类的临时对象并用此临时对象来构造当前对象,这种转换必须有构造函数的支持;operator算子的隐式类型转换,使用当前对象去生成另一个类型的对象(正好与构造函数隐式转换相反),这种转换必须有operator算子的支持。当然了,构造函数的隐式类型转换有利有弊,类的设计者就起决定性作用了,如果你不想让构造函数发生隐式的类型转换,请在构造函数前加explicit关键字;同时,operator算子声明的隐式类型转换也可以通过一些相应的返回值函数替代,用户的掌控性更好。

最后,用过实现一个经常发生的普遍需求(string转其他基本数据类型)让读者加深一下,operator自定义对象类型的隐式转换功能的用法。

   template <typename T>
class string_cast
{
public:
string_cast(const std::string &from): m_from(from) {
}
operator T() const {
std::stringstream sstr(m_from);
T ret;
try {
sstr >> ret;
}
catch(std::exception &e)
{
return T();
}
return ret;
}
private:
const std::string &m_from;
};

string转int的用法:

cout << string_cast<int>("") << endl;

string转double的用法:

cout << string_cast<double>("12345.78") << endl;

是不是和c++的其他类型转换(static_cast,const_cast,dynamic_cast, reinterpret_cast)语法很相似?

c++ operator操作符的两种用法:重载和隐式类型转换,string转其他基本数据类型的简洁实现string_cast的更多相关文章

  1. 用ECMAScript4 ( ActionScript3) 实现Unity的热更新 -- 操作符重载和隐式类型转换

    C#中,某些类型会定义隐式类型转换和操作符重载.Unity中,有些对象也定义了隐式类型转换和操作符重载.典型情况有:UnityEngine.Object.UnityEngine.Object的销毁是调 ...

  2. [VC]C++ operator 两种用法

    C++中的operator,有两种用法,一种是operator overloading(操作符重载),一种是operator casting(操作隐式转换).下面分别进行介绍:   1.operato ...

  3. operator用法:隐式类型转换

    operator它有两种用法,一种是operator overloading(操作符重载),一种是operator casting(操作隐式转换). 1.操作符重载C++可以通过operator实现重 ...

  4. operator 的两种用法

    C++,有时它的确是个耐玩的东东,就比如operator,它有两种用法,一种是operator overloading(操作符重载),一种是operator casting(操作隐式转换).1.操作符 ...

  5. C++操作符operator的另一种用法

    http://blog.csdn.net/memewry/article/details/7833314 参考地址 今天在程序员面试宝典上看到这样一道题目:  A C++ developer want ...

  6. Service的两种用法及其生命周期

    先来一点基础知识: Service 是android的四大组件之一,与Activity同属于一个级别,它是运行在后台进行服务的组件(例如在后台播放的音乐,播放音乐的同时并不影响其他操作).Servic ...

  7. JSP中的include的两种用法

    1.两种用法 <%@ include file=” ”%> <jsp:include page=” ” flush=”true”/> 2.用法区别 (1)执行时间上区别 < ...

  8. 子查询。ANY三种用法。ALL两种用法。HAVING中使用子查询。SELECT中使用子查询。

    子查询存在的意义是解决多表查询带来的性能问题. 子查询返回单行多列: ANY三种用法: ALL两种用法: HAVING中的子查询返回单行单列: SELECT中使用子查询:(了解就好,避免使用这种方法! ...

  9. Comparable和Comparator的区别&Collections.sort的两种用法

    在Java集合的学习中,我们明白了: 看到tree,可以按顺序进行排列,就要想到两个接口.Comparable(集合中元素实现这个接口,元素自身具备可比性),Comparator(比较器,传入容器构造 ...

随机推荐

  1. 传入的表格格式数据流(TDS)远程过程调用(RPC)协议流不正确。此 RPC 请求中提供了过多的参数。最多应为 2100

    出现这个问题的背景是,判断一批激活码在系统中是否已经存在,很傻的一个作法是,把这一批激活码,以in(in (‘ddd‘,‘aaa‘))的形式来处理,导致问题的出现. 后来,查找资料,http://bb ...

  2. js继承相关

    这几天看到一篇文章详解Javascript的继承实现,发现js还是很深奥的,比如call.apply.prototype这些,问起来我也能说的头头是道的,但是看到一些复杂的代码有的时候还是会迷糊,所以 ...

  3. 黑马------synchronized详解

    黑马程序员:Java培训.Android培训.iOS培训..Net培训 JAVA线程-synchronized详解 一.synchronized概述 1.线程间实现互斥,必须使用同一个监视器(一个对象 ...

  4. golang http服务器跨域问题解决

    func main() { openHttpListen() } func openHttpListen() { http.HandleFunc("/", receiveClien ...

  5. Linux软件的安装方法!!!

    1.yum/rpm(*.rpm) 包管理器:直接yum/rpm安装. 优点:是全自动化安装,不需要为依赖问题发愁,缺点是自主性太差,软件的功能.存放位置固定,不易变更. 2.源码包(*.tar.gz) ...

  6. How to ssh to your Amazon Elastic Beanstalk instance?

    Well, if it's ec2 or a digital ocean server, it would be a lot easier- you do what you normally do f ...

  7. 浅谈GPU

    Programmable Graphics Processing Unit(GPU),可编程图形处理单元,可编程图形硬件. 98年NVIDIA的modern GPU研发成功,使用晶体管(transis ...

  8. LintCode Minimum Path Sum

    Given a m x n grid filled with non-negative numbers, find a path from top left to bottom right which ...

  9. [读书笔记]Java之动态分派

    以下内容来自周志明的<深入理解Java虚拟机>. 前一篇说了静态分派和重载有关,现在的动态分派就和覆盖Override有关了. 先看代码: public class DynamicDisp ...

  10. php查询文件扩展名

    //查询文件扩展名 function extension($str){ $str = implode("",explode("\\",$str)); $str ...