广告位联系
返回顶部
分享到

C++中类的转换函数介绍

C#教程 来源:互联网 作者:秩名 发布时间:2022-03-14 09:19:15 人浏览
摘要

只有接受一个参数(其他参数有默认值的也算)的构造函数才能作为转换构造函数。 在C++中,接受一个参数的构造函数为将类型与该参数相同的值转换为类提供了蓝图。因此,下面的构

只有接受一个参数(其他参数有默认值的也算)的构造函数才能作为转换构造函数。

在C++中,接受一个参数的构造函数为将类型与该参数相同的值转换为类提供了蓝图。因此,下面的构造函数用于将double类型的值转换为Stonewt类型:

1

Stonewt(double lbs) // double转Stonewt的模板

也就是说,可以编写这样的代码:

1

2

Stonewt myCat; // 创建一个Stonewt对象

myCat = 19.6; // 使用Stonewt(double)将19.6转换为Stonewt对象

这一过程称为隐式转换,因为它是自动进行的,而不需要显式强制类型转换。

将构造函数用作自动类型转换似乎是一项不错的特性。然而,当程序员拥有更丰富的C++经验时,将发现这种自动特性并非总是合乎需要的,因为这会导致意外的类型转换。因此,C++新增了关键字explicit,用于关闭这种自动特性。也就是说,可以这样声明构造函数:

1

explicit Stonewt(double lbs) // 不允许隐式转换

这将关闭上述示例中介绍的隐式转换,但仍然允许显式转换,即显式强制类型转换:

1

2

3

4

Stonewt myCat;

myCat = 19.6; // 不允许,因为Stonewt(double)声明为explicit

myCat = Stonewt(19.6); // OK,一个显示地转换

myCat = (Stonewt)19.6; // OK,原始地显示类型转换

编译器在什么时候将使用Stonewt(double)函数呢?

如果在声明中使用了关键字explicit,则Stonewt(double)将只用于显式强制类型转换,否则还可以用于下面的隐式转换:

  • 将Stonewt对象初始化为double值时。如:Stonewt st(1.23);
  • 将double值赋给Stonewt对象时。如:Stonewt st; st = 1.23;
  • 将double值传递给接受Stonewt参数的函数时。如:display(Stonewt& st);-> display(1.23);
  • 返回值被声明为Stonewt的函数试图返回double值时。如:Stonewt& go(){ return 1.23; }
  • 在上述任意一种情况下,使用可转换为double类型的内置类型时。如:Stonewt& go() { return 123; }

可以将数字转换为Stonewt对象。可以做相反的转换吗?也就是说,是否可以将Stonewt对象转换为double值,就像如下所示的那样?

1

2

Stonewt wolfe(285.7);

double host = wolfe;// ??可以吗??

可以这样做,但不是使用构造函数。构造函数只用于从某种类型到类类型的转换。要进行相反的转换,必须使用特殊的C++运算符函数——转换函数。

转换函数是用户定义的强制类型转换,可以像使用强制类型转换那样使用它们。例如,如果定义了从Stonewt到double的转换函数,就可以使用下面的转换:

1

2

3

4

5

6

Stonewt wolfe(285.7);

double host = double (wolfe);    // syntax #1

double thinker = (double) wolfe; // syntax #2

也可以让编译器来决定如何做:

Stonewt wells(20, 3);

double star = wells; // 隐式使用转换函数

编译器发现,右侧是Stonewt类型,而左侧是double类型,因此它将查看程序员是否定义了与此匹配的转换函数。(如果没有找到这样的定义,编译器将生成错误消息,指出无法将Stonewt赋给double。)

创建一个转换函数,转换为typeName类型,需要使用这种形式的转换函数:

operator typeName();// 无返回类型,无参数

请注意以下几点:

  • 转换函数必须是类方法
  • 转换函数不能指定返回类型
  • 转换函数不能有参数

在类的头文件定义:

1

2

operator int() const;

operator double() const;

实现代码:

1

2

3

4

5

6

7

8

9

10

11

12

13

14

15

......

// construct Stonewt object from stone, double values

Stonewt::Stonewt(int stn, double lbs) {

    stone = stn;

    pds_left = lbs;

    pounds = stn * Lbs_per_stn + lbs;

}

......

// conversion functions

Stonewt::operator int() const {

    return int(pounds + 0.5);

}

Stonewt::operator double() const {

    return pounds;

}

使用:

1

2

3

4

5

6

Stonewt poppins(9, 2.8);// 9 stone, 2.8 pounds

double p_wt = poppins;// implicit conversion

cout << "Convert to double => ";

cout << "Poppins: " << p_wt << " pounds.\n";

cout << "Convert to int => ";

cout << "Poppins: " << int(poppins) << " pounds.\n";

1

2

Convert to double => Poppins: 128.8 pounds.

Convert to int => Poppins: 129 pounds.

原则上说,最好使用显式转换,而避免隐式转换。在C++98中,关键字explicit不能用于转换函数,但C++11消除了这种限制。因此,在C++11中,可将转换运算符声明为显式的:

1

2

3

4

5

6

class Stonewt {

    ...

    // 转换函数

    explicit operator int() const;

    explicit operator double() const;

};

有了explicit声明后,在显式强制转换时才调用这些运算符。

另一种方法是,用一个功能相同的非转换函数替换该转换函数即可,但仅在被显式地调用时,该函数才会执行。也就是说,可以将:

1

2

3

Stonewt::operator int() { return int (pounds + 0.5); }

替换为:

int Stonewt::Stone_to_Int() { return int (pounds + 0.5); }

这样,下面的语句:

1

2

3

4

int plb = poppins; // 非法

int plb1 = (int) poppins;// 合法

int plb2 = int(poppins);// 合法

int plb3 = poppins.Stone_to_Int(); // 合法

应谨慎地使用隐式转换函数。通常,最好选择仅在被显式地调用时才会执行的函数。


版权声明 : 本文内容来源于互联网或用户自行发布贡献,该文观点仅代表原作者本人。本站仅提供信息存储空间服务和不拥有所有权,不承担相关法律责任。如发现本站有涉嫌抄袭侵权, 违法违规的内容, 请发送邮件至2530232025#qq.cn(#换@)举报,一经查实,本站将立刻删除。
原文链接 : https://blog.csdn.net/itzyjr/article/details/123448216
相关文章
  • WPF实现窗体亚克力效果的代码

    WPF实现窗体亚克力效果的代码
    WPF 窗体设置亚克力效果 框架使用大于等于.NET40。 Visual Studio 2022。 项目使用MIT开源许可协议。 WindowAcrylicBlur设置亚克力颜色。 Opacity设置透
  • C#非托管泄漏中HEAP_ENTRY的Size对不上解析

    C#非托管泄漏中HEAP_ENTRY的Size对不上解析
    一:背景 1. 讲故事 前段时间有位朋友在分析他的非托管泄漏时,发现NT堆的_HEAP_ENTRY的 Size 和!heap命令中的 Size 对不上,来咨询是怎么回事?
  • C#中ArrayList 类的使用介绍
    一:ArrayList 类简单说明 动态数组ArrayList类在System.Collecions的命名空间下,所以使用时要加入System.Collecions命名空间,而且ArrayList提供添加,
  • C#使用BinaryFormatter类、ISerializable接口、XmlSeriali

    C#使用BinaryFormatter类、ISerializable接口、XmlSeriali
    序列化是将对象转换成字节流的过程,反序列化是把字节流转换成对象的过程。对象一旦被序列化,就可以把对象状态保存到硬盘的某个位
  • C#序列化与反序列化集合对象并进行版本控制
    当涉及到跨进程甚至是跨域传输数据的时候,我们需要把对象序列化和反序列化。 首先可以使用Serializable特性。 1 2 3 4 5 6 7 8 9 10 11 12 13 14
  • C#事件中关于sender的用法解读

    C#事件中关于sender的用法解读
    C#事件sender的小用法 开WPF新坑了,看了WPF的炫酷界面,再看看winForm实在是有些惨不忍睹(逃)。后面会开始写一些短的学习笔记。 一、什么
  • 在C#程序中注入恶意DLL的方法

    在C#程序中注入恶意DLL的方法
    一、背景 前段时间在训练营上课的时候就有朋友提到一个问题,为什么 Windbg 附加到 C# 程序后,程序就处于中断状态了?它到底是如何实现
  • 基于C#实现一个简单的FTP操作工具
    实现功能 实现使用FTP上传、下载、重命名、刷新、删除功能 开发环境 开发工具: Visual Studio 2013 .NET Framework版本:4.5 实现代码 1 2 3 4 5 6 7
  • C#仿QQ实现简单的截图功能

    C#仿QQ实现简单的截图功能
    接上一篇写的截取电脑屏幕,我们在原来的基础上加一个选择区域的功能,实现自定义选择截图。 个人比较懒,上一篇的代码就不重新设计
  • C#实现线性查找算法的介绍
    线性查找,肯定是以线性的方式,在集合或数组中查找某个元素。 通过代码来理解线性查找 什么叫线性?还是在代码中体会吧。 首先需要一
  • 本站所有内容来源于互联网或用户自行发布,本站仅提供信息存储空间服务,不拥有版权,不承担法律责任。如有侵犯您的权益,请您联系站长处理!
  • Copyright © 2017-2022 F11.CN All Rights Reserved. F11站长开发者网 版权所有 | 苏ICP备2022031554号-1 | 51LA统计