C++类对象之间的类型转换和重载
类对象和其他类型对象的转换
转换场合有:
赋值转换
表达式中的转换
显式转换
函数调用,
传递参数时的转换 转换方向有:
由定义类向其他类型的转换
由其他类型向定义类的转换
#include <math.h> #include <iostream>
using std::cout;
using std::endl; class Complex
{
public:
Complex(double dreal, double dimag)
: _dreal(dreal)
, _dimag(dimag)
{} void display() {
cout << _dreal << " + " << _dimag << "i" << endl;
} friend std::ostream & operator<<(std::ostream & os, const Complex & rhs);
private:
double _dreal;
double _dimag;
}; std::ostream & operator<<(std::ostream & os, const Complex & rhs)
{
if(rhs._dreal == 0 && rhs._dimag != 0)
os << rhs._dimag << "i";
else {
os << rhs._dreal;
if(rhs._dimag > 0)
os << " + " << rhs._dimag << " i";
else if (rhs._dimag < 0)
os << " - " << rhs._dimag * (-1) << " i";
}
return os;
} class Point
{
public:
Point(int ix = 0, int iy = 0)
: _ix(ix)
, _iy(iy)
{
cout << "Point(int=0, int=0)" << endl;
} //由自定义类型向其他类型进行转换
//
//类型转换函数
//1. 必须是成员函数
//2. 没有返回值类型
//3. 在函数体内必须用return 语句以传值方式返回一个目标类型的变量(对象)
//4. 没有形参
//5. 一般情况下,不要使用它, 因为它违反了常规思维方式 operator int()
{
cout << "operator int()" << endl;
return _ix;
} operator double()
{
cout << "operator double()" << endl;
return _ix * _iy;
} operator Complex()
{
cout << "operator Complex()" << endl;
return Complex(_ix, _iy);
} void print() const
{
cout << "(" << _ix
<< "," << _iy
<< ")" << endl;
} friend std::ostream & operator<<(std::ostream & os, const Point & rhs);
private:
int _ix;
int _iy;
}; std::ostream & operator<<(std::ostream & os, const Point & rhs)
{
os << "(" << rhs._ix
<< "," << rhs._iy
<< ")";
return os;
} int main(void)
{
Point pt1(1, 2); int x = pt1;
cout << "x = " << x << endl; double dvalue = pt1;
cout << "dvalue = " << dvalue << endl; Complex cx = pt1;
cout << "cx = " << cx << endl; return 0;
}
由其他类型向定义类的转换
- 由其他类型(如int、double)等向自定义类的转换是由构造函数来实现的,只有当类的定义和实现中提供了合适的构造函数时,转换才能通过。什么样的构造函数才是合适的构造函数呢?主要有以下几种情况,为便于说明,假设由int类型向自定义point类转换:
- point类的定义和实现中给出了仅包括只有一个int类型参数的构造函数 Point pt1 = 5;
- point类的定义和实现中给出了包含一个int类型参数,且其他参数都有缺省值的构造函数
- point类的定义和实现中虽然不包含int类型参数,但包含一个非int类型参数如float类型,此外没有其他参数或者其他参数都有缺省值,且int类型参数可隐式转换为float类型参数。
- 在构造函数前加上关键字explicit可以关闭隐式类型转换
//9-12 由其他类型转换到自定义类型
#include <iostream>
using namespace std; class point; class anotherPoint //anotherPoint类定义
{
private: //private成员列表
double x;
double y; public:
anotherPoint(double xx = 1, double yy = 1) //构造函数,带缺省参数值
{
x = xx;
y = yy;
} void print() //输出函数,点的信息
{
cout << "( " << x << " , " << y << " )";
} friend class point; //使point类成为本类的友元类, 这样point
//类就可以访问anotherPoint 类的private变量了
}; class point //point类定义
{
private: //private成员列表
int xPos;
int yPos; public:
// explicit //如果在构造函数前加上explicit, 就不允许 point pt1 = 5这种隐式转换了
point(int x = 0, int y = 0) //构造函数,带缺省参数,两个int型变量
{
xPos = x;
yPos = y;
} point(anotherPoint aP) //构造函数,参数为anotherPoint类对象
{
xPos = aP.x; //由于point类是anotherPoint类的友元类,
yPos = aP.y; //因此这里可以访问anotherPoint的私有变量x和y
} void print() //输出函数,点的信息
{
cout << "( " << xPos << " , " << yPos << " )" << endl;
}
}; int main()
{
//1. 将int类型数字5转换成point类型
point p1; //创建point类对象p1,采用带缺省参数的构造函数,即x=0、y=0
cout << 5 << " 转换成 ";
p1 = 5; //等价于p1=point(5,0);
p1.print(); //输出点p1的信息 //2. 将double类型变量dX转换成point类型
double dX = 1.2; //声明一个double变量dX
cout << dX << " 转换成 ";
p1 = dX; //等价于p1=point(int(dX),0)
p1.print(); //输出点p1的信息 //3. 将anotherPoint类型转换成point类型
anotherPoint p2(12.34, 56.78); //创建anotherPoint类的对象p2
p2.print();
cout << " 转换成 ";
p1 = p2; //等价于p1=point(p2);
p1.print(); //输出点p1的信息 //4. 测试在point构造函数前加上explicit以阻止隐性转换的情况 return 0;
}
类型转换函数
- 可以通过operator int()这种类似操作符重载函数的类型转换函数来实现由自定义类型向其他类型的转换。如将point类转换成int类型等。
- 在类中定义类型转换函数的形式一般为:
operator 目标类型名();
- 有以下几个使用要点:
- 转换函数必须是成员函数,不能是友元形式。
- 转换函数不能指定返回类型,但在函数体内必须用return语句以传值方式返回一个目标类型的变量。
- 转换函数不能有参数。
//类型转换函数(由类转换成其他类型)
#include <iostream>
using namespace std; class point;
ostream & operator<<(ostream &os, const point &pt); class anotherPoint //anotherPoint类定义
{
private: //private成员列表
double x;
double y; public:
anotherPoint(double xx = 1.11, double yy = 1.11)//构造函数,带缺省参数值
{
x = xx;
y = yy;
} void print() //成员函数,输出点的信息
{
cout << "( " << x << " , " << y << " )" << endl;
}
}; class point //Point类定义
{
private: //private成员列表
int xPos;
int yPos; public:
point(int x = 0, int y = 0) //构造函数,带缺省参数值
{
xPos = x;
yPos = y;
} void print() //成员函数,输出点的信息
{
cout << "( " << xPos << " , " << yPos << " )" << endl;
} friend ostream & operator<<(ostream &os, const point &pt); // 重载<<运算符 operator int() //定义Point向int型的转换函数int()
{
return xPos;
} operator double() //定义Point向double型的转换函数double()
{
return xPos * yPos;
} operator anotherPoint() //定义Point向anotherPoint型的转换函数anotherPoint()
{
return anotherPoint(xPos, yPos);
}
}; ostream & operator<<(ostream &os, const point &pt)
{
os << (pt.xPos * 100);
return os;
} int main()
{
point p1(4, 5); //声明一个point类变量p1
p1.print(); //1. point转换成int
int x1 = p1; //p1赋值给一个int型变量,point中的转换函数int()被隐式调用
cout << x1 << endl; //2. point转换成double
double dX = p1; //p1赋值给一个double型变量,point中的转换函数double()被隐式调用
cout << dX << endl; //3. point转换成anotherPoint
anotherPoint p2; //声明anotherPoint类对象p2,构造函数采用缺省值
p2 = p1; //p1赋值给p2,point中的转换函数anotherPoint()被隐式调用
//等价于p2=anotherpoint(p1.xPos,p1.yPos)
p2.print(); //看p2是否修改成功 return 0;
}
C++类对象之间的类型转换和重载的更多相关文章
- 存在继承关系的Java类对象之间的类型转换(一)
类似于基本数据类型之间的强制类型转换. 存在继承关系的父类对象和子类对象之间也可以 在一定条件之下相互转换. 这种转换需要遵守以下原则: 1.子类对象可以被视为是其父类的一个对象2.父类对象不能被 ...
- C++:基类与派生类对象之间的赋值兼容关系
4.5 基类与派生类对象之间的赋值兼容关系 在一定条件下,不同类型的数据之间可以进行类型转换,例如可以将整型数据赋给双精度型变量. 在赋值之前,先把整型数据转换为双精度型数据,然后再把它双精度型变量. ...
- 浅谈C++中对象的复制与对象之间的相互赋值
C++对象的复制 有时需要用到多个完全相同的对象,例如,同一型号的每一个产品从外表到内部属性都是一样的,如果要对每一个产品分别进行处理,就需要建立多个同样的对象,并要进行相同的初始化,用以前的办法定义 ...
- C++学习6-面向对象编程基础(运算符重载、类的派生与继承、命名空间)
运算符重载 重载的运算符是具有特殊名字的函数:它们的名字由关键字operator和其后要定义的运算符号共同组成.重载的运算符是遵循函数重载的选择原则,根据不同类型或不同参数来选择不同的重载运算符. 运 ...
- Java对象多态性——对象的转型(引用类型之间的类型转换)
Java引用变量有两个类型:编译时类型和运行时类型.编译时类型由声明该变量时使用的类型决定,运行时类型由实际赋给该变量的对象决定. 若编译时类型和运行时类型不一致,就出现多态 正常的方法调用(本态调用 ...
- PHP类和对象之间的关系
类是对象的描述: 类和对象之间的关系类似于建房子的图纸和房子: 创建类--new对象--用对象: 一.对象的两个特性: --对象的行为(功能):可以对对象施加操作,例如,电视机的开.关.转换频道: - ...
- java类和对象之间的差
java类和对象之间的差别是一个普遍的问题,刚开始学习java当它来到与类和对象接触.今天就来总结一下它们之间的差异. 先说说class和object差异.事实上,词:object是全部class的父 ...
- C#用反射实现两个类的对象之间相同属性的值的复制
在进行实体转换操作的时候如果需要在对两个实体之间两个属性字段差不多相同的类要进行一个互相的转换,我们要把a对象的所有字段的值都复制给b对象,我们只能用b.属性=a.属性来写,如果属性字段太多的话,就要 ...
- 2.java面向对象类与类/类与对象之间关系详解
继承.实现.依赖.关联.聚合.组合的联系与区别 下面的内容很基础,同时也很简单,但是也很重要. 继承 指的是一个类(称为子类.子接口)继承另外的一个类(称为父类.父接口)的功能,并可以增加它自己的新功 ...
随机推荐
- Why is chkconfig no longer available in Ubuntu?
Question: I can not use chkconfig tools in Ubuntu 12.10 It's a very useful tools to configure the se ...
- 浅谈MySQL外键
http://www.xiaoxiaozi.com/2009/07/12/1158/ 像MySQL这样的关系型数据库管理系统,它们的基础是在数据库的表之间创建关系的能力.通过方便地在不同表中建立记录到 ...
- ffmpeg 内存池
ffmpeg 部分内存管理采用 了内存池技术.基本的接口在libavutil目录下的buffer.c文件中实现: 1. av_buffer_pool_init 初始化 内存池 2 av_buffer_ ...
- 数据库历险记(三) | 缓存框架的连环炮 数据库历险记(二) | Redis 和 Mecached 到底哪个好? 数据库历险记(一) | MySQL这么好,为什么还有人用Oracle? 面对海量请求,缓存设计还应该考虑哪些问题?
数据库历险记(三) | 缓存框架的连环炮 文章首发于微信公众号「陈树义」,专注于 Java 技术分享的社区.点击链接扫描二维码,与500位小伙伴一起共同进步.微信公众号二维码 http://p3n ...
- vue入门-常用指令操作
指令:v-xx组成的特殊指令,如果一个标签中有指令会默认替换原有的书 v-model:实现数据和视图的双向绑定 v-text:在元素中插入值 v-html:在元素中插入标签或者插入文本 v-if:根据 ...
- poj 1703 Find them, Catch them(种类并查集和一种巧妙的方法)
Find them, Catch them Time Limit: 1000MS Memory Limit: 10000K Total Submissions: 36176 Accepted: ...
- eclipse代码注释模版
设置注释模板的入口: Window->Preference->Java->Code Style->Code Template 然后展开Comments节点就是所有需设置注释的元 ...
- spring2实现定时任务的一种方式
1. 在项目中放入Spring的jar包 2. applicationContext.xml的<beans xmlns>部分,添加context相关内容: <beans xmlns= ...
- mysql-connector-java与mysql版本的对应
记录下mysql-connector-java与mysql版本的对应关系,已方便以后参考,这是最新版本对应, 时间:2017年5月23日 官网文档地址: https://dev.mysql.com/d ...
- ASP.NET MVC4中ViewBag、ViewData和TempData的使用和区别
一.说明 本文章主要是讲解asp.net mvc中ViewBag.ViewData和TempData的使用和区别,ViewBag.ViewData和TempData常常用于将action方法中的数据传 ...