C++primer读书笔记9转换与类类型

有时候指定了自己类类型来表示某种类型数据如SmallInt,那么为了方便计算就会指定一个转换操作符,将该类类型在某种情况下自动的转换为指定的类型

<1>转换操作符

operator type();

转换函数必须是类成员函数,不能指定返回类型,并且形参列表必须为空,并且通常不应该改变转换对象,所以操作符通常定义为const成员。

#include <iostream>
using namespace std;
class SmallInt
{
public:
	SmallInt(int i=0):val(i)
	{ if(i<0 || i>255) throw std::out_of_range("Bad SmallInt initializer");}
	~SmallInt(void){};
	operator int()const
	{std::cout<<"Translate SmallInt to Int"<<endl;return val;}
private:
	size_t val;
};

<2>2级转换

我们在SmallInt中指定的转换是int,但是SmallInt可以间接的转换为其他标准类型如double,float等

SmallInt sm;
double dv;
sm >= dv	//sm convet to int and then convert to double
if(sm)		//sm convet to int and then convert to bool
int x = static_cast<int>(si) + 2;	// instruct compiler SmallInt to int

<3>禁止转换

假设还有一个类Integral,它可以转换为SmallInt,但是它不能发生2级变换从Integral转换成SmallInt然后再转换成int类型。

int cal(int);
Integral intVal;
cal(intVal);	//error,no convertion to int from Integral

总之:

SmallInt ->standard type ->standard type	//ok
standard type ->standard type->SmallInt		//ok
Integral->SmallInt->Int				//error

在转换中只能用到一个类类型转换(类类型<->标准类型,类类型<->类类型

<4>不要在一个类中指定多个类类型转换

这样可能会引起在一些转换时候的二义性。

class SmallInt
{
public:
	SmallInt(int i=0):val(i){ if(i<0 || i>255) throw std::out_of_range("Bad SmallInt 

initializer");}
	SmallInt(double db):val(db){}
	~SmallInt(void){};
	operator int()const{std::cout<<"Translate SmallInt to Int"<<endl;return val;}
	operator double()const{std::cout<<"Translate SmallInt to double"<<endl;return val;}
private:
	size_t val;
};

void fpComputer(float)
{}
SmallInt sm(100);
fpComputer(sm) 	//error 

<5>构造函数转换二义性

void manip(const SmallInt&);
double d;
int i;
float f;
mamip(d);	//ok,use SmallInt(double) to convert
manip(i);	//ok,use SmallInt(int) to convert
manip(f);	//error,ambiguous

<6> 构造函数转换和类类型转换同时存在时候的二义性

class Integral;
class SmallInt
{
public:
	SmallInt(Integral);
	//...
};
class Intergal
{
public:
	operator SmallInt()const;
	//...
}
void compute(SmallInt);
Integral intVal;
compute(intVal);	//error:ambiguous

这里的Integral类型的变量intVal可以通过构造函数以及类类型转换两种方式转换成SmallInt,所以具有二义性

,具体的解决方法是通过显式方式调用如下所示:

compute(intVal.operator SmallInt());
compute(SmallInt(intVal));

C++primer读书笔记9转换与类类型

时间: 2024-10-18 17:28:04

C++primer读书笔记9转换与类类型的相关文章

C++ Primer 学习笔记_64_重载操作符与转换 --转换与类类型【下】

重载操作符与转换 --转换与类类型[下] 四.重载确定和类的实参 在需要转换函数的实参时,编译器自动应用类的转换操作符或构造函数.因此,应该在函数确定期间考虑类转换操作符.函数重载确定由三步组成: 1)确定候选函数集合:这些是与被调用函数同名的函数. 2)选择可行的函数:这些是形参数目和类型与函数调用中的实参相匹配的候选函数.选择可行函数时,如果有转换操作,编译器还要确定需要哪个转换操作来匹配每个形参. 3)选择最佳匹配的函数.为了确定最佳匹配,对将实参转换为对应形参所需的类型转换进行分类.对于

C++ Primer 学习笔记_63_重载操作符与转换 --转换与类类型【上】

重载操作符与转换 --转换与类类型[上] 引言: 在前面我们提到过:可以用一个实参调用的非explicit构造函数定义一个隐式转换.当提供了实参类型的对象需要一个类类型的对象时,编译器将使用该转换.于是:这种构造函数定义了到类类型的转换. 除了定义到类类型的转换之外,还可以定义从类类型到其他类型的转换.即:我们可以定义转换操作符,给定类类型的对象,该操作符将产生其他类型的对象.和其他转换一样,编译器将自动应用这个转换. 一.转换为什么有用? 定义一个SmallInt的类,该类实现安全小整数,这个

C++ Primer 学习笔记_63_重载运算符和转换 --转换和类类型【上】

重载运算符和转换 --转换与类类型[上] 引言: 在前面我们提到过:能够用一个实參调用的非explicit构造函数定义一个隐式转换.当提供了实參类型的对象须要一个类类型的对象时.编译器将使用该转换. 于是:这样的构造函数定义了到类类型的转换. 除了定义到类类型的转换之外,还能够定义从类类型到其它类型的转换.即:我们能够定义转换操作符,给定类类型的对象.该操作符将产生其它类型的对象.和其它转换一样,编译器将自己主动应用这个转换. 一.转换为什么实用? 定义一个SmallInt的类,该类实现安全小整

C++ primer读书笔记10-继承

封装,继承,多态是C++的三大基本概念,这里着重总结一下继承相关的东西 1 类派生列表 类派生列表指定派生类要继承的基类,派生列表中有一个或者多个基类如: class B : public A1,protected A2,private A3 但是单继承时最常见的,多继承不多见 2 派生类的定义 派生类继承时,会包含父类的所有成员,即便私有成员不能被访问.父类中的虚函数,在派生类中一般也要定义,如 果不定义的话,派生类将继承基类的虚函数 3 基类必须是已经定义的 一个仅仅声明的类,是不能出现在派

C++primer读书笔记11-多态

多态也是C++中的一个重要的方面,多态和动态类型,虚函数本质上是指相同的事情. 1 虚函数 类中的成员函数原型前面加上virtual 表面这个函数是个虚函数.虚函数的目的是为了在继承它的派生类中重新定义这个函数,以便于通过基类的指针或引用在运行时对派生类的函数进行调用. 2 派生类和虚函数 派生类一般情况下要重定义所继承的虚函数,有几个注意事项. <1>虚函数的声明必须和基类中的函数声明原型完全一致,例外的是当基类返回基类型的指针或者引用的时候,派生类可以派生类类型的指针或者引用 <2&

C++中的volatile(Primer读书笔记)

时间:2014.05.24 地点:基地 -------------------------------------------------------------------------- 一.简述 volatile限定符平时很少用到,今天倒是碰到了,所幸探个明白.volatile 英文字面意思是"不稳定的",确切的计算机含义时与机器相关,所以在对包含volatile的程序在移植到新机器或使用不同的编译器时往往还需要对编译器进行一些改变. -----------------------

《C++ Primer Plus》读书笔记之九—使用类

第十一章 使用类 1.操作符函数的格式:operator op(argument-list).op是将要重载的操作符. 2.操作符重载函数的两种调用方式:①函数表示法:C=A.operator+(B);A.B.C都是类对:②操作符表示法:C=A+ B:操作符左侧的对象A是调用对象,操作符右边的对象B是作为参数被传递的对象. 3.不要返回指向局部变量或临时对象的引用,函数执行完毕后,局部变量和临时对象将消失,引用将指向不存在的数据. 4.C++对用户定义的操作符重载的限制:①重载的操作符不必是成员

C++ Primer 读书笔记

1,命令编译生成的默认输出文件(可执行文件) 命名为:a.out(Unix), a.exe(Windows) 2,cout输出首先会存到缓存中,而printf之类的输出会直接输出到输出流中. 3,可以从键盘上输入End-Of-File:Ctrl+d(Unix), Ctrl+z(Windows). 4,C++中最常见的三种编译错误:1)类型错误,将值赋给不同类型的变量:2)声明错误,使用未声明的变量,或者在同一个域中重复声明一个变量:3)语法错误,写错语法. 5,可以通过command <infi

C++primer读书笔记8重载操作符

函数的重载操作符中也有不少细节 1 重载操作符特点 重载操作符本质上就是重载函数,它的特点: <1>除了函数调用操作符'()'外,所有的重载操作符的形参数目必须与操作符的操作数目相等. <2>重载操作符的操作数必须至少有一个类类型,否则就不是重载而是原型了. <3>优先级和结合性不会发生改变,例如对于算数操作符的重载,*的优先级肯定还是大于+ <4>不具有短路求值特性(就是根据已有的值就可以判断出最终的逻辑结果的话就会停止计算) <5>操作符可以