iis服务器助手广告广告
返回顶部
首页 > 资讯 > 后端开发 > 其他教程 >C++中用户怎么自定义转换过程
  • 167
分享到

C++中用户怎么自定义转换过程

2023-06-17 12:06:30 167人浏览 泡泡鱼
摘要

本篇文章为大家展示了c++中用户怎么自定义转换过程,内容简明扼要并且容易理解,绝对能使你眼前一亮,通过这篇文章的详细介绍希望你能有所收获。传统转换方式(Traditional Type-Casting)C++作为C语言的超集,完全继承了C语

本篇文章为大家展示了c++中用户怎么自定义转换过程,内容简明扼要并且容易理解,绝对能使你眼前一亮,通过这篇文章的详细介绍希望你能有所收获。

传统转换方式(Traditional Type-Casting)

C++作为C语言的超集,完全继承了C语言所具有的类型转换方法和能力,因此对于这部分在基础数值类型上的转换是比较容易理解的。但是因为C++是面向对象的语言,有类的概念,因此让又多一层需要理解的内容。

隐式转换 (Implicit Conversion)

隐式转换不需要任何转换运算符,编译器会自动根据类型兼容性进行不同类型之间的转换。一般情况下,在C/C++中这种转换多出现在基本数值类型上,其基本原则就是所需内存小的类型可以直接转换成内存大相同的或者。

内存大小相同的类型之间也可以互相转换,但是得到的结果可能不是预期的,因而可能会得到编译器的警告。比如 unsigned int uintVariable = -1; 。

虽说:程序员只在意错误(Error),不关心警告(Warning),但是导师也是严令禁止在程序中出现的,所以对于这样的隐式转换也会尽量避免。

显示转换 (Explicit Conversion)

显示转换要表明所要转换的目标对象是什么样的类型,然后编译器会做出转换,它有两种格式:

C语言格式(C-like Cast) (new_type) expression

函数式(Function-style Cast) new_type (expression)

示例代码

#include <iOStream>using namespace std;      int main() {int x0 = 100;      float num0 = x0;      float num = 98.76;      int x1 = (int) num;      int x2 = int(num);          cout << "num0 = " << num0 << endl;      cout << "x1 = " << x1 << endl;      cout << "x2 = " << x2 << endl;      cout << "x3 = " << x3 << endl;}

对于C++的类而言,也可以在其实例对象上使用传统的类型转换

这是利用了C++的一些语言特性。

下边就以例子来做解释

代码

#include<iostream>  #include<string>  using namespace std;  //Macro definitions#define    IDER_DEBUG 1#define FUNC_TRAC(info)   {if(IDER_DEBUG)cout<<"----"<<info<<"----"<<endl;}//class declarationclass Human;class Ape;  class Programmer;//class definitionclass Programmer{public:      Programmer(string where = "genius")      {          FUNC_TRAC("Programmer Default Constructor");         from = where;      }            void Speach(){cout<<"I am a Programmer, I am "<< from <<endl;}private:      string from;};class Human {public:      Human(string where = "delivered by Parents"):heart("Human with Training")      {          FUNC_TRAC("Human Default Constructor");           from = where;    }      Human(Ape& a):heart("Human with Practice")      {        FUNC_TRAC("Hummer Ape-Promotion Constructor");          from = "Evolution from an Ape";      }       operator Programmer() //here is weird, it is really different whether we have "&" or not      {          FUNC_TRAC("Hummer Programmer-Cast Operator");         return heart;           //Programmer("Human with Practice");   // it is not Good to return temporary variable      }      Human& operator =(Human& h)    {          FUNC_TRAC("Hummer Assignment Operator");         cout<<"Call assignment"<<endl;           return *this;      }      void Speach(){cout<<"I am a Human, I am "<< from <<endl;}      private:      string from;      Programmer heart; //Every one has a heart to be a programmer};class Ape {public:      Ape(string where = "from Nature")      {          FUNC_TRAC("Ape Default Constructor");           from = where;      }      Ape& operator =(Programmer& p)      {          FUNC_TRAC("Ape Programmer-Assignment Operator");           from="Degeneration from a Programmer";           return *this;      }            void Speach(){cout<<"#(*%^, !@#$&)( "<< from <<endl;}private:      string from;};//main functionint main(void) {      Ape a;      //a.Speach();       Human h = a; // using promtion constructor      //h.Speach();          Human h3;      h3 = a; // Error, no match assignment opeartor        Programmer p = h; // using Programmer-cast operaotor      //p.Speach();      Programmer p0;      p0 = h;      // using  Programmer-cast operaotor          Programmer p1 = h.operator Programmer();    Programmer p2 = Programmer(h);      Programmer p3 = (Programmer)h;      Ape a2;      a2 = p; //using assignment operator      //a2.Speach();          Ape a3 = p; // Error, no match constructor      return 0;}

在这个例子中,我定义了三个类,这三个类之间没有继承和被继承的关系,也没有friend关系,其基本联系就是:Ape可以进化成为Human,Human经过不断的训练就可以成为Programmer,不过Programmer也有可能退化变成Ape。

分析

从main函数中他们进行的转换操作,可以看出这是一种隐式的转换。不过三个类的对象之间能够实现转换的真正原因却并不相同。

首先,从Ape到Human的转换方式

Human h = a;

其实是调用了Human的promotion构造函数

Human(Ape& a);

这个函数接受了Ape作为构造参数,实例化了一个Human对象。

从Human到 Programmer,则是因为我在Human中定义了一个到Programmer的转换运算符:

operator Programmer()

因此,在main函数中的两个赋值语句:

Programmer p = h;  p0 = h;

都是调用了这个转换函数。

从Programmer退化到Ape是一件很不情愿的事情(就因为在中文里,我们是程序猿),在代码中的实现方式,则是在Ape类中定义了一个接受Programmer引用作为参数的Assignment运算符的重载形式。

Ape& operator =(Programmer& p)

于是下边的语句

a2 = p;

就得以在程序中运行了

进一步分析

已经看到了Ape, Human,Programmer的之间的转换都是使用了不同的C++特性,调用的是不同的方法。但是深究起来,这些方法还是各有个的不同。

以Human到Programmer为基准,这个转换用的是用户自定义转换(user-defined cast),因此可以说这种方式才是真正的类型之间的转换。

也因此我们在main中看到了两种语法格式的转换都是有效的:

定义并初始化

Programmer p = h;

赋值

p0 = h;

但是Ape到Human的转换调用的构造函数,因此它只有在类实例化对象并初始化的时候才有效,也因此下边的语句会得到编译器的错误:

Human h3;  h3 = a; // Error, no match assignment opeartor

因为Human从出生就知道自己是怎么来的,不应该后来才发现自己不是妈生的(当然,这些情况不是不可能的,比如“人猿泰山”)。

而Programmer到Ape是后天形成的,不然一出生就变成猴子了,那就只能用脚趾了coding了。所以以下代码也是编译不过的:

Ape a3 = p; // Error, no match constructor

在回过来讲讲Human到Programmer,我们还可以用更多不同的形式来写,比如两种形式的显示转换:

Programmer p1 = Programmer(h);  Programmer p2 = (Programmer)h;

(是初始化还是赋值都无所谓)

但是真正编译之后,其格式应该是:

Programmer p3 = h.operator Programmer();

对于Assignment运算符其实也是如此,真正调用的还是:

a2.operator =(p);

后记

其实在实际编程中,可能受到了C#的影响(因为C#的初始化并不是得到一个全新的对象,而只是获得引用),并不会经常使用到用户自定义转换,也很少重载一个接受非自身对象引用的Assignment运算符。

真正要转换的时候,多数还是通过构造函数进行。或者是,实例化好对象,通过两者的接口对数据进行赋值。毕竟以上讲到各种方式中,也只能调用到接收到对象的外部接口,不能进行私有数据的操作。

关于数值类型的转换和类对象的转换,前面都已经提到了,但似乎还遗漏了什么?

是的,C++还有引用类型(reference)和指针类型(pointer)。这两者在不同类型之间的转换还没有说。

在C++中,指针类型似乎是被视为是没有差异的,想想的确如此,因为它只是存放所指对象的地址,因此所需内存空间、格式都是一致的,也因此在C++不同类型 之间的指针是可以随意转换的,一般需要用显示转换。但是这种转换是没有意义,因为地址所指的类型并非所需要的类型,通过该地址进行偏移找到的数据或方法就不会是我们所需要的了,在运行的时候,程序就会发生异常。

对于引用类型,在没有继承关系的类型之间进行转换似乎也并不合理,引用其实在实现上可以被视为指针,只是在语法格式上,它被当做对象使用。如果进行引用类型的转换,我们到底是想要一个新的对象呢,还是只要地址?让人迷糊。

另外,指针和引用的应该是用在已经存在的对象或对象变量上。因此如果是转换中返回转换运算符的方法之内的一个局部变量(像Human类的operator Programmer()方法中我注释掉的那行代码),那么在离开转换运算符的方法之后,那些变量就会被回收,在指向那些地址也是没有意义了;如果是在内部new一个心的对象,这个对象的管理就变得没有约束性,我们不知道该在何时会去delete它;即使像我实现的那样,在Human类中带着一个Programmer的对象Heart,但是这个设计似乎也并不是非常好的,因为不能保证每个人都有一颗作为程序员的心。

遗留问题

前面也提到了指针和引用在类型转换上的问题,因此对于用户自定义转换符,在我的代码中,我所使用的是基于对象的转换:

operator Programmer();

不是基于指针:

operator Programmer*();

也不是基于引用

operator Programmer&()

在我看来,这是合理的,也是合适的。

但是如果我在Programmer类中定义了一个copy构造函数,那么无论以上提到4种的从Human到Programmer的代码格式都得到编译错误。

这似乎可以理解:编译器会从构造函数中发现合适的入口,但是它失败了,所以就错误了。

但是为何

h.operator Programmer();

上述内容就是C++中用户怎么自定义转换过程,你们学到知识或技能了吗?如果还想学到更多技能或者丰富自己的知识储备,欢迎关注编程网其他教程频道。

--结束END--

本文标题: C++中用户怎么自定义转换过程

本文链接: https://www.lsjlt.com/news/289119.html(转载时请注明来源链接)

有问题或投稿请发送至: 邮箱/279061341@qq.com    QQ/279061341

本篇文章演示代码以及资料文档资料下载

下载Word文档到电脑,方便收藏和打印~

下载Word文档
猜你喜欢
  • C++中用户怎么自定义转换过程
    本篇文章为大家展示了C++中用户怎么自定义转换过程,内容简明扼要并且容易理解,绝对能使你眼前一亮,通过这篇文章的详细介绍希望你能有所收获。传统转换方式(Traditional Type-Casting)C++作为C语言的超集,完全继承了C语...
    99+
    2023-06-17
  • C#中怎么自定义类型转换函数
    C#中怎么自定义类型转换函数,针对这个问题,这篇文章详细介绍了相对应的分析和解答,希望可以帮助更多想解决这个问题的小伙伴找到更简单易行的方法。/// <summary>  /// 将字符型...
    99+
    2023-06-18
  • 怎么在Golang中转换自定义类型
    怎么在Golang中转换自定义类型?很多新手对此不是很清楚,为了帮助大家解决这个难题,下面小编将为大家详细讲解,有这方面需求的人可以来学习下,希望你能有所收获。golang适合做什么golang可以做服务器端开发,但golang很适合做日志...
    99+
    2023-06-06
  • C#类型转换之自定义隐式转换和显式转换
    目录前言基础知识示例代码实际应用问题答案报错其他应用和设计读音前言 有时我们会遇到这么一种情况:在json数据里,数组里的数据类型不一致,导致我们不能直接反序列化为目标类型。最终我们...
    99+
    2024-04-02
  • C#怎么创建用户自定义异常
    本篇内容主要讲解“C#怎么创建用户自定义异常”,感兴趣的朋友不妨来看看。本文介绍的方法操作简单快捷,实用性强。下面就让小编来带大家学习“C#怎么创建用户自定义异常”吧!创建用户自定义异常您也可以定义自己的异常。用户自定义的异常类是派生自&n...
    99+
    2023-06-17
  • C#中如何实现自定义类型的转换
    在C#中,我们可以通过实现类型转换运算符(conversion operators)来自定义类型的转换。具体步骤如下: 创建一个自...
    99+
    2024-04-03
    C#
  • springmvc怎么自定义类型转换器
    要自定义类型转换器,首先需要创建一个实现了Converter接口的转换器类,然后在Spring MVC的配置文件中注册这个转换器。 ...
    99+
    2024-04-02
  • C#如何实现自定义隐式转换和显式转换
    这篇文章主要介绍了C#如何实现自定义隐式转换和显式转换,具有一定借鉴价值,感兴趣的朋友可以参考下,希望大家阅读完这篇文章之后大有收获,下面让小编带着大家一起了解一下。基础知识类型转换有2种:隐式转换和显式转换。但是,不管是隐式转换,还是显式...
    99+
    2023-06-29
  • Django 中怎么自定义用户模块
    这篇文章将为大家详细讲解有关Django 中怎么自定义用户模块,文章内容质量较高,因此小编分享给大家做个参考,希望大家阅读完这篇文章后对相关知识有一定的了解。1、概述Django中自带的User Model使用起来是比较方便的,但是通常我们...
    99+
    2023-06-02
  • Java怎么自定义强制类型转换
    在Java中,可以使用自定义方法来实现强制类型转换。下面是一个示例:```javapublic class MyClass {pub...
    99+
    2023-09-27
    Java
  • C++中怎么自定义类
    这篇文章将为大家详细讲解有关C++中怎么自定义类,文章内容质量较高,因此小编分享给大家做个参考,希望大家阅读完这篇文章后对相关知识有一定的了解。/////////////TestClass.h/////////////////// &nbs...
    99+
    2023-06-17
  • 怎么在C++中定义RTTI的类型进行转换
    这篇文章给大家介绍怎么在C++中定义RTTI的类型进行转换,内容非常详细,感兴趣的小伙伴们可以参考借鉴,希望对大家能有所帮助。前言RTTI 是 Run Time Type Information 的缩写,从字面上来理解就是执行时期的类型信息...
    99+
    2023-06-07
  • PostgreSQL怎么实现用户自定义
    本篇内容介绍了“PostgreSQL怎么实现用户自定义”的有关知识,在实际案例的操作过程中,不少人都会遇到这样的困境,接下来就让小编带领大家学习一下如何处理这些情况吧!希望大家仔细阅读,能够学有所成!Bis...
    99+
    2024-04-02
  • python用户怎么自定义异常
    本篇内容主要讲解“python用户怎么自定义异常”,感兴趣的朋友不妨来看看。本文介绍的方法操作简单快捷,实用性强。下面就让小编来带大家学习“python用户怎么自定义异常”吧!说明程序可以通过创建一个新的异常类来命名它们自己的异常。异常应该...
    99+
    2023-06-20
  • C#中怎么使用自定义数据
    本篇文章为大家展示了C#中怎么使用自定义数据,内容简明扼要并且容易理解,绝对能使你眼前一亮,通过这篇文章的详细介绍希望你能有所收获。C#语言有很多值得学习的地方,这里我们主要介绍C#自定义数据,包括介绍每一个由DBObject派生的对象都拥...
    99+
    2023-06-17
  • Java中的BaseTypeHandler自定义类型转换器的使用
    目录简述通用的类型转换器(存在一些问题)定制类型转换器简述 mysq5.7之后新增了json类型,但是在使用的过程中,Json数组中的值小于Integer.MAX_VALUE,则反序...
    99+
    2024-04-02
  • C#中propertygrid控件怎么自定义使用
    要自定义使用C#中的PropertyGrid控件,您可以使用以下步骤:1. 创建一个Windows窗体应用程序或者一个自定义控件。2...
    99+
    2023-10-10
    C#
  • Spring中的类型转换器怎么定义使用
    这篇文章主要讲解了“Spring中的类型转换器怎么定义使用”,文中的讲解内容简单清晰,易于学习与理解,下面请大家跟着小编的思路慢慢深入,一起来研究和学习“Spring中的类型转换器怎么定义使用”吧!1.类型转换器作用类型的转换赋值2.自定义...
    99+
    2023-07-04
  • 如何使用JPA自定义VO类型转换
    这篇文章主要介绍如何使用JPA自定义VO类型转换,文中介绍的非常详细,具有一定的参考价值,感兴趣的小伙伴们一定要看完!JPA自定义VO类型转换(EntityUtils工具类)在JPA查询中,如果需要返回自定义的类,可以使用EntityUti...
    99+
    2023-06-25
  • .Net自定义转换器JsonConverter的使用详解
    目录场景描述通过JsonSerializerOptions参数,绑定JsonConverter来实现在实体类的属性上 增加JsonConverter注解来实现参考官方文档 场景描述 ...
    99+
    2023-05-17
    .net 自定义转换器JsonConverter 自定义转换器JsonConverter使用
软考高级职称资格查询
编程网,编程工程师的家园,是目前国内优秀的开源技术社区之一,形成了由开源软件库、代码分享、资讯、协作翻译、讨论区和博客等几大频道内容,为IT开发者提供了一个发现、使用、并交流开源技术的平台。
  • 官方手机版

  • 微信公众号

  • 商务合作