目标:

已知这个接口:

std::vector<double> add_vec(double *d1, double *d2)
{
.....
return result;
}

我们自定义了这个类:

class array
{
int size_;
double *data_;
....
};

要求实现:

array v1(10), v2(10);
add_vec(v1, v2);

留意到,当array 类型传入add_vec时,会遇到(double*) 类型的“试探性”强制转换, 所以,我们只要做一个从array到,(double*)的类型转换即可。

这样做的好处

  • 1.有了类型转换,我们不需要再写这样一个多态函数实现array 与array的相加
std::vector<double> add_vec(array d1, array d2)
{
.....
return result;
}
  • 2.以下的接口:
std::vector<double> add_vec(double* d1, double* d2)

可能重写起来非常麻烦,甚至add_vec(double*, double*) 是别人封装好的,我们看不到源代码,此时更谈不上重写

实现方法及测试代码:(直接在这个代码上增加,所以代码有些乱)

C++类型转换操作符(type conversion operator)

#include <iostream>

 class D {
public:
D(double d) : d_(d) {
data_=new double[10];
for(int i=0; i<10; i++)
data_[i]=d;
} ~D() { delete []data_; } /* “(int)D”类型转换 */
operator int() const {
std::cout << "(int)d called!" << std::endl;
return static_cast<int>(d_);
} // for: double me= *d1; //ok
double& operator*(void) {
return *data_;
} // for: double *me2= (double*)d1;
operator double*(void){
return data_;
} private:
double d_;
double *data_;
}; int add(int a, int b) {
return a + b;
} #include <vector>
std::vector<double> add_vec(double* d1, double* d2)
{
std::vector<double> r(10);
for(int i=0; i<10; i++){
r[i]=d1[i]+d2[i];
} return r;
} int main() {
D d1 = 1.1;
D d2 = 2.2;
std::cout << add(d1, d2) << std::endl; double me= *d1; //ok
std::cout<<"me:"<<me<<std::endl;
double *me2= (double*)d1; // ok std::vector<double> r;
r=add_vec(d1, d2);
for(int i=0; i<r.size(); i++){
std::cout<<r[i]<<" "<<std::endl;
} //std::cout << add_vec(d1, d2) << std::endl; return 0;
}

输出:

(int)d called!
(int)d called!
3
me:1.1
3.3 
3.3 
3.3 
3.3 
3.3 
3.3 
3.3 
3.3 
3.3 
3.3

补充:

注意到:

    double me=    *d1;
double *me= (double*)d1;

第二个的意义为把 D类型当成一个指针, 然后把把指针(即地址)赋值给me

第一个意义为:把D类型先假设指针,然后把指针指向的值转给me

二者等价,所以,可删除其中一个冗余定义,经过测试,代码仍能正常运行

    // for: double *me2= (double*)d1;
operator double*(void){
return data_;
}

但是如果:

    // for: double me=    *d1;      //ok
double& operator*(void) {
return *data_;
}

则会报错:

Press ENTER or type command to continue
main.cpp: In function ‘int main()’:
main.cpp:62:27: error: invalid cast from type ‘D’ to type ‘double*’
main.cpp:63:18: error: invalid conversion from ‘int’ to ‘double*’ [-fpermissive]
main.cpp:69:21: error: invalid conversion from ‘int’ to ‘double*’ [-fpermissive]
main.cpp:44:21: error:   initializing argument 1 of ‘std::vector<double> add_vec(double*, double*)’ [-fpermissive]
main.cpp:69:21: error: invalid conversion from ‘int’ to ‘double*’ [-fpermissive]
main.cpp:44:21: error:   initializing argument 2 of ‘std::vector<double> add_vec(double*, double*)’ [-fpermissive]

仔细理解,编译器这样做是有道理的,因为第一个重载只是第一个的特殊情况,不能包括第一个,而第二个重载却能包含第一个

更多参见

Can a cast operator be explicit?

How do conversion operators work in C++?

C++库研究笔记——操作符重载实现类型转换&这样做的意义的更多相关文章

  1. C#中如何利用操作符重载和转换操作符 (转载)

    操作符重载 有的编程语言允许一个类型定义操作符应该如何操作类型的实例,比如string类型和int类型都重载了(==)和(+)等操作符,当编译器发现两个int类型的实例使用+操作符的时候,编译器会生成 ...

  2. C#构造函数、操作符重载以及自定义类型转换

    构造器 构造器(构造函数)是将类型的实例初始化的特殊方法.构造器可分为实例构造器和类型构造器,本节将详细介绍有关内容. 实例构造器 顾名思义,实例构造器的作用就是对类型的实例进行初始化.如果类没有显示 ...

  3. 21.C++- "++"操作符重载、隐式转换之explicit关键字、类的类型转换函数

    ++操作符重载 ++操作符分为前置++和后置++,比如: ++a;  a++; ++操作符可以进行全局函数或成员函数重载 重载前置++操作符不需要参数 重载后置++操作符需要一个int类型的占位参数 ...

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

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

  5. C#中如何利用操作符重载和转换操作符

    操作符重载 有的编程语言允许一个类型定义操作符应该如何操作类型的实例,比如string类型和int类型都重载了(==)和(+)等操作符,当编译器发现两个int类型的实例使用+操作符的时候,编译器会生成 ...

  6. C++ operator overload -- 操作符重载

    C++ operator overload -- 操作符重载 2011-12-13 14:18:29 分类: C/C++ 操作符重载有两种方式,一是以成员函数方式重载,另一种是全局函数. 先看例子 # ...

  7. C++基础知识:操作符重载

    1.C++标准库: C++标准库并不是C++语言的一部分C++标准库是由C++语言编写而成的类库和函数的集合C++标准库中定义的类和对象都位于std命名空间中C++标准库的头文件都不带.h后缀C++标 ...

  8. C++学习笔记-操作符重载

    操作符重载(operator overloading)是一种形式的C++多态,C++将操作符重载扩展到用户自定义的类型,如允许使用+将两个自定义的对象相加,编译器将根据操作数的数目和类型决定使用那种加 ...

  9. 侯捷STL学习(四)--OOP-GP/操作符重载-泛化特化

    C++标准库第二讲 体系结构与内核分析 第1-7节为第一讲 读源代码前的准备 第八节:源代码分布 C++基本语法 模板的使用 数据结构和算法 本课程主要使用:Gnu C 2.9.1与Gun C 4.9 ...

随机推荐

  1. Jqgrid入门-操作表格的数据(二)

    上一篇中,Jqgrid已经可以从服务端获得数据,并显示在Grid表格中了.下面说一下,如何操作表格及其数据.           jqGrid有很多方法函数,用来操作数据或者操作Grid表格本身.jq ...

  2. Asp.Net Unix时间戳和DateTime类型转换

    using System; using System.Collections.Generic; using System.Web; using System.Web.UI; using System. ...

  3. [ASP.NET 技术点滴] Jquery 前端验证

    先上HTML代码: <form id="login" name="login" action="~/f_login/Login" me ...

  4. 【 D3.js 高级系列 — 6.0 】 值域和颜色

    在[入门 - 第 10 章]作了一张中国地图,其中各省份的颜色值都是随意赋值的.如果要将一些值反映在地图上,可以利用颜色的变化来表示值的变化. 1. 思路 例如,有值域的范围为: [10, 500] ...

  5. Android UI——分享一个登录缓冲界面

    效果如上图 所示 :就是下面的 loading  字母会按顺序一个个的 动起来 ,很好的效果 代码说明 请参考 该文:http://blog.csdn.net/xyz_lmn/article/deta ...

  6. iOS-利用AFNetworking(AFN 1.x)-实现文件断点下载

    转:http://www.kaifazhe.com/ios_school/380066.html 官方建议AFN的使用方法 1. 定义一个全局的AFHttpClient:包含有 1> baseU ...

  7. 应用市场高速下载以及网页端调起APP页面研究与实现

    Github博文地址,此处更新可能不是很及时. 好久没写博客了,好大一个坑.正好,最近刚做完应用市场的高速下载功能,便拿来填了这个坑. 话说产品为了增加用户量,提升用户活跃度以及配合推广,更坑爹的是看 ...

  8. C# chart控件绘制曲线

    在.NET中以前经常用GDI去绘制,虽然效果也不错,自从.NET 4.0开始,专门为绘制图表而生的Chart控件出现了,有了它,就可以轻松的绘制你所需要的曲线图.柱状图什么的了. using Syst ...

  9. HDU5764 After a Sleepless Night 树形乱搞题

    分析(官方题解): 假设根已确定,可以发现新树若合法,需满足以下性质:根节点是n:儿子的值不大于父亲:具有相同值的节点形成一条链,并且链不会发生“分叉”(即有多个最低点).所以对于新树中有出现的值x, ...

  10. Web Notification

    在OS X 10.8 Mountain Lion系统上,通过Safari访问的页面能够发送通知到系统右边栏通知中心,通知(Notification)是通过WebKit Notification 对象发 ...