精华内容
下载资源
问答
  • C++隐式类型转换

    2019-08-18 22:03:57
    一、什么是隐式转换隐式转换是编译器完成的,帮助程序继续完成任务的一个手段。 二、怎么使用隐式转换? 编译器自动完成转换,需要特别注意转换的效果是否符合预期。 三、什么时候发生隐式转换 条件语句中,非...

    一、什么是隐式转换?

    隐式转换是编译器完成的,帮助程序继续完成任务的一个手段。

    二、怎么使用隐式转换?

    编译器自动完成转换,需要特别注意转换的效果是否符合预期。

    三、什么时候发生隐式转换

    • 条件语句中,非bool转换成boolif(998)->if(true)
    • 初始化语句中,初始值转换成变量类型 int pi=3.14->int pi=3
    • 赋值语句中,右侧对象转换成左侧对象,double pi;pi=3->double pi=3.000000000000000
    • 关系、算术运算符类型不一样,都转换成同一类型。int + double + double->double+double+double
    • 函数调用时,实参转换成形参类型。
    • 构造函数仅有一个参数且没有被声明为explicit的函数,出现参数不匹配时进行的一步转换

    四、分类

    4.1 算术类型隐式转换

    对象的类型定义了对象所能包含的数据和参与的运算,一种运算能够被大多数对象支持靠的就是转换,将操作数两边的转成同一类型再进行运算。如:

    double+int->double+double
    

    一个重要规则就是:运算符对象将会转换成两者中最宽的类型。

    4.2 初始化隐式转换

    初始化时,初始值向声明的变量类型转换。

    4.3 其他类型隐式转换

    • 数组转为指针。
    • 指针的转换。整数0(NULL)或nullptr转换成任意指针;非常量指针转换成void *’;任意指针转换成const void *,继承关系基类和派生类转换;指针转换成bool(条件语句)
    • 转换成常量。int i;const int &j=i,“虽然你不是常量,但是我可以把你看成是常量”。
    展开全文
  • 类的转换,C++的内部数据类型遵循隐式类型转换规则,成员转换函数
  • C++语言中,类型转换有两种方式,隐式类型转换和显示类型转换。 1. 隐式类型转换 在有隐式类型转换的表达式中,不需要明确指定一个类型的对象该转换为另外哪一个类型,这个工作将隐含地由编译器来完成,编译器将...

    C++ 语言是一种强类型语言,当我们需要用一种类型的对象来替代另一种类型的对象进行相关操作时,必须首先进行类型转换。C++语言中,类型转换有两种方式,隐式类型转换和显示类型转换。

    1. 隐式类型转换

    在有隐式类型转换的表达式中,不需要明确指定一个类型的对象该转换为另外哪一个类型,这个工作将隐含地由编译器来完成,编译器将分析表达式的含义,进行类型转换。

    隐式类型转换针对不同的类型有不同的转换方式,总体可以分为两种类型,算术类型和类类型。

    1.1 算术类型转换

    算术类型转换的设计原则是尽可能避免损失精度。

    具体地,有以下几条参考规则:

    1. 整型提升:将小整数类型转换成较大的整数类型。例如,如果一个运算对象的类型是long double,那么另外一个运算对象,无论它的类型是什么,都会被转换成long double。
    2. 有符号类型转换为无符号类型。类型转换一般不会改变对象内存的值,当一个有符号类型的对象转换为无符号类型时,其表示出来的值可能发生变化,例如,int a = -1 (0xff); unsigned int b = a; 则b的值为255。
    3. 在条件判断中,非布尔类型自动转换为布尔类型。如果指针或算术类型的值为0,转换为false,否则转换为true。

    类型级别从高到低的顺序是long double, double, float, unsigned long long, long long, long, unsigned int 和 int。

    1.2 类类型转换

    在C++中,可以通过定义单参数构造函数或者转换函数来进行类类型转换,这种方式也称为用户定义的转换(User-Defined Conversion)。这种方式在使用的时候不需要指明转换类型,而是由编译器自动进行选择转换函数,所以也是一种隐式类型转换。

    用户定义的类类型转换可以由编译器自动执行,但是编译器每次只能执行一种类类型的转换。如果一个类型转换为另外一个类型,需要同时进行多次转换,这种转换将会失败。

    1.2.1 转换构造函数

    如果构造函数只接受一个参数,则它实际上定义了转换为此类类型的隐式转换机制,我们把这种构造函数称为转换构造函数。在转换中只允许一步类类型的转换。

    最常见的例子就是将C类型字符串转换为string类型,例如 string s = "hello world",因为string类有一个构造函数string(const char *s)。

    我们可以自定义一个类类型如下:

    class Sales_data {
    public:
        Sales_data() = default;
        Sales_data( const std::string &s ) : bookNo( s ) { }
        Sales_data( const std::string &s, unsigned n, double p ) :
            bookNo( s ), units_sold( n ), revenue( p*n ) { }
        Sales_data( std::istream & );
    
        std::string isbn() const { return bookNo; }
        Sales_data& combine( const Sales_data& );
    
    private:
        std::string     bookNo;
        unsigned        units_sold;
        double          revenue;
    };

    在上述例子中,由于Sales_data( const std::string &s );构造函数的存在,因此存在string类型到Sales_data的转换,因此在需要Sales_data对象的时候,我们可以使用string类型替代。

    Sales_data item;
    string null_book = "9-999-99999-9";
    item.combine( null_book );

    只有一次的隐式类类型转换是可行的,而item.combine( "9-999-99999-9" )是错误的,因为在该语句中,存在着两次隐式转换,一次是字符串常量"9-999-99999-9"到string的转换,另一次是string到Sales_data的转换。

    explicit constructors: 
    如果你不想隐式转换,以防用户误操作怎么办? 
    可以通过将构造函数声明为explicit来阻止隐式转换。explicit构造函数只能用于直接初始化。不允许编译器执行其它默认操作(比如类型转换,赋值初始化)。
    关键字explicit只对一个实参的构造函数有效。

    1.2.2 类型转换函数

    在类类型转换中,我们通常有两个需求,一个是将其他类型的数据转换为我们自定义类的类型,另一个是将自定义类的类型在需要的时候转换为其他的数据类型。转换构造函数能很好地满足前一个需求,针对后面一个需求,我们除了可以使用普通的成员函数进行显示转换,在C++中,还可以使用类型转换函数进行隐式转换。

    类型转换函数的作用就是将一个类的对象转换成另一类型的数据。

    我们经常写下述代码:

    while( cin >> num ){
        ...
    }

    输入操作符 >> 是二元操作符,返回做操作数作为其表达式结果,因此cin >> num返回cin,然而cin是输入流istream的对象,该对象能出现在条件表达式中,是因为在istream中定义了类型转换函数 operator bool();

    类型转换函数一般形式:

    operator 目标类型()
    {
        ...
        return 目标类型数据;
    }
    

    例如:

    class A {
    public:
        A(const int x) : _x(x) {}
        operator int() { return _x; }
    private:
        int _x;
    };
    
    int main () {
        A a(10);
        int res = a + 20;
        std::cout << res << std::endl;
    }

    输出结果为30.
    由于类A定义了从该类对象到int类型的转换函数,所以在进行整数算术运算的时候,可以直接使用该类对象,因为编译器会隐式地调用该类型转换函数将类对象转换为整型数据。

    2. 显示类型转换

    显示类型转换就是在表达式中明确指定将一种类型转换为另一种类型。隐式类型转换一般是由编译器进行转换操作,显示类型转换是由程序员写明要转换成的目标类型。显示类型转换又被称为强制类型转换。

    2.1 C风格的强制转换

    C风格的强制转换很简单,不管什么类型的转换都可以使用使用下面的方式。

    type val = (type)(expression);

    当然,C++支持C风格的强制转换,但是C风格的强制转换可能带来一些隐患,让一些问题难以察觉。

    2.2 C++命名的强制类型转换

    C++提供了4个命名的强制类型转换,它们都有如下的基本形式:

    type val = cast-name<type>(expression);

    cast-name是static_cast、dynamic_cast、const_cast、reinterpret_cast中的一种。在这里简单探讨一下。

    2.1.1 static_cast

    static_cast 很像 C 语言中的旧式类型转换。它能进行基础类型之间的转换,也能将带有可被单参调用的构造函数或用户自定义类型转换操作符的类型转换,还能在存有继承关系的类之间进行转换(即可将基类转换为子类,也可将子类转换为基类),还能将 non-const对象转换为 const对象(注意:反之则不行,那是const_cast的职责)。

    static_cast 转换时并不进行运行时安全检查,所以是非安全的,很容易出问题。因此 C++ 引入 dynamic_cast 来处理安全转型。

    2.1.2 dynamic_cast

    dynamic_cast 主要用来在继承体系中的安全向下转型。它能安全地将指向基类的指针转型为指向子类的指针或引用,并获知转型动作成功是否。如果转型失败会返回null(转型对象为指针时)或抛出异常(转型对象为引用时)。dynamic_cast会使用运行时信息(RTTI)来进行类型安全检查,因此dynamic_cast存在一定的效率损失。(我曾见过属于优化代码80/20法则中的20那一部分的一段游戏代码,起初使用的是dynamic_cast,后来被换成 static_cast 以提升效率,当然这仅是权宜之策,并非好的设计。)

    2.1.3 const_cast

    前面提到 const_cast 可去除对象的常量性(const),它还可以去除对象的易变性(volatile)。const_cast 的唯一职责就在于此,若将 const_cast 用于其他转型将会报错。

    2.1.4 reinterpret_cast

    reinterpret_cast 用来执行低级转型,如将执行一个 int 的指针强转为 int。其转换结果与编译平台息息相关,不具有可移植性,因此在一般的代码中不常见到它。reinterpret_cast 常用的一个用途是转换函数指针类型,即可以将一种类型的函数指针转换为另一种类型的函数指针,但这种转换可能会导致不正确的结果。总之,reinterpret_cast 只用于底层代码,一般我们都用不到它,如果你的代码中使用到这种转型,务必明白自己在干什么。

    展开全文
  • 1.什么是类型转换 ...转换规则由编译器自动执行,无需程序员介入 3.何时产生隐式类型转换 1)在混合类型的表达式中,其操作数转换为相同的类型. (操作符的两边) int ival; int dval; i

    1.什么是类型转换

    某些类型之间存在相关的依赖关系,在需要某种类型的操作数位置上,使用该类型的相关类型的值或对象.

    2.什么是隐式类型转换

    转换规则由编译器自动执行,无需程序员介入

    3.何时产生隐式类型转换

    1)在混合类型的表达式中,其操作数转换为相同的类型.
    (操作符的两边)
    int ival;
    int dval;
    ival>=dval

    2)用作条件表达式被转换成bool类型.
    int ival=3;
    if(ival)
    ;

    3)用一表达式初始化某个变量或将以表达式赋值给某个变量,则该表达式被转换为该变量的类型.
    (操作符的两边)
    int val=3.14;//将3.14强制转换成int类型
    int *p=0;//将int 0转换为int指针的空指针.

    4)函数调用时产生的隐式类型转换
    形参与实参
    实参的类型与其对应的形参类型匹配:实参必须有与形参类型相同或者能隐式转换为形参类型的数据类型
    (顺便备注一句:函数重载确定,即函数匹配,之前在写一个封装打印输出函数时,曾出现错误,std::string char*类型中有个出错了,现在想想还是对函数重载概念不够清晰)

    4.为什么扯这些.

    只看explicit关键字,说的很简单,但是自己看过两三次,看primer,总是感觉有些东西不够透.但如果深究原因的其实很简单,explicit就是关于类类型隐式转换的关键字.何时产生,产生的原理何在,就是上面所描述隐式类型转换方面的东西.
    东西要联系起来看,每个都不是孤立的.知其然,知其所以然.

    5.explicit 关键字

    1.产生类类型隐式转换条件

    单个形参来调用构造函数定义了从形参类型到该类类型的一个隐式转换.
    如果没有单个形参,或者单个形参加explicit关键字,在3中描述产生隐式转换情况,根本不会进行隐式转换.反之,当处于3中描述的情形中,就会产生隐式类类型转换.

    2.怎样使用explicit

    构造函数声明为explicit,来防止在需要隐式转换的地方使用构造函数.定义时则不需要再加入explicit.
    Boost timer类中,只有一个参数的构造函数使用了explicit,含有两个参数即以上的构造函数,没有加入explicit.

    3.类类型隐式转换过程

    1. class Sales_item    
    2. {    
    3. public:     
    4.     Sales_item(const std::string & book);    
    5.     Sales_item(std::istream & is);    
    6. };    
    7.     
    8. bool same_isbn(Sales_item book)    
    9. {    
    10. }    
    11.     
    12. std::string null_book = "9-999-99999-9";    
    13. item.same_isbn(null_book);    
    14. item.same_isbn(cin);    

    单参数的构造函数使类类型隐式转换有了可能.
    在same_isbn函数中需要Sales_item类型.但是由于有了string单个参数构造函数,null_book会隐式转换成类型Sales_item.如何转换?
    item.same_isbn(null_book); 
    实质上等于
    item.same_isbn(Sales_item(null_book));
    cin也是一样.

    6.关于explicit 一个小结.

           C++ Primer中提到:通常,除非有明显的理由想要定义隐式转换,否则,但形参构造函数应该为explicit。将构造函数设置为explicit可以避免错误,而且当转换有用时,用户可以显式地构造对象。
           

           google的c++规范中提到:explicit的优点是可以避免不合时宜的类型变换,缺点无。所以google约定所有单参数的构造函数都必须是显示的,只有极少数情况下拷贝构造函数可以不声明称explicit。例如作为其他类的透明包装器的类。

           effective c++中提到:被声明为explicit的构造函数通常比其non-explicit兄弟更受欢迎。因为它们禁止编译器执行非预期(往往也不被期望)的类型 转换。除非我有一个好理由允许构造函数被用于隐式类型转换,否则我会把它声明为explicit。我鼓励你遵循相同的政策。



    另外一篇比较不错的博客:

    http://blog.csdn.net/shuangshuang37278752/article/details/14143093

    展开全文
  • 隐式类型转换构造函数:

    转自公众号:码农有道

    1. 隐式类型转换构造函数:

        在《C++ Primer》这本经典教程中提到:可以用单个实参来调用的构造函数定义从形参类型到该类类型的一个隐式转换。这句话看起来比较绕口挺不好理解的。我们还是结合实例来理解。

    #include <iostream>
    using namespace std;
    
    class Complex{
    public:
        Complex(double r, double i=0)
            :m_real(r), m_imag(i){
            cout<<"constructor function:"<<endl;
            cout<<"m_real = "<<m_real<<" m_imag = "<<m_imag<<endl;
        }
        Complex(){
            cout<<"No-argument constructor function:"<<endl;
        }
        friend void print(Complex c);
    private:
        double m_real;
        double m_imag;
    };
    
    void print(Complex c){
        cout<<"m_real = "<<c.m_real<<" m_imag = "<<c.m_imag<<endl;
    }
    
    int main(int argc, char *argv[])
    {
        Complex c1 = 5;    //1
        Complex c2;
        c2 = 4;            //2
        print(10);         //3
        return 0;
    }


    上面的例子中,Compex(double r, double i = 0)这个构造函数就是前面所说的可以用单个实参来调用的构造函数 ,因为它的第二个参数是默认参数。像这样的函数也称为转换构造函数

    那什么又是从形参类型到该类类型的一个隐式转换了?在上例中,1,2,3处(截图中已经标明)就发生了所谓的从形参类型到该类类型的一个隐式转换 。

    我们以第3处的函数调用print(10)为例,由于print 函数定义时是接收一个Complex类型的参数,现在调用时传了个10,由于转换构造函数的存在,可以将10隐式转换为一个临时Complex 对象传递过去

    看到没,通过10得到了Complex对象,这就是以转换构造函数形参类型此处是double类型---10可以隐式转换为double类型)到该类类型 (这个临时对象)隐式转换 

    到这里,我相信大家应该明白了什么是隐式转换构造函数了吧。

    2. 隐式转换的隐患

        隐式类型转换表面上看给我们带来了很大的方便,但是实际上很多时候却会给我们代码埋下很深的隐患,看看下面的代码。

    #include <iostream>
    using namespace std;
    
    class MyString{
    public:
        MyString(int size){} //构造函数
        MyString(const char* s=NULL){}//构造函数2
    };
    
    int main(){
        MyString s1 = 'a';//这里原意是想用字符串"a"初始化s1,
                            //结果不小心将双引号""打成单引号''
        return 0;
    }

    从上面可以看出,第14行原本我们是想写 Mystring s1 = "a",通过构造函数2将s1初始化为字符串"a"的,结果不小心将双引号" "写成了单引号' ',由于转换构造函数1(功能是创建size大小的字符串)的存在,它会用'a'构造出一个临时的Mystring 对象(含97(a的ascii码)字节的字符串)来初始化s1。结果s1被初始化为了含97字节的字符串。

    上面那种情况并不是我们希望的,程序运行的时候,凡是用到s1的地方都可能出现逻辑错误,而这种错误又是很难定位的。

    那么有没有一种办法可以预防这种情况的发生?现在是该我们讲述explicit 关键字的时候了。

    3. explicit 关键字用法

        好了,经过前面那么长铺叠,现在终于轮到我们的主角explicit 登场了,前面说了隐式转换常常会带来程序逻辑的错误,而且这种错误一旦发生是很难察觉的,应当尽量避免。

        那么怎么避免这种隐式转换 ,这就是关键字explicit的作用了,在声明构造函数的时候前面添加上explicit即可,这样就可以防止这种转换。  C++中的explicit关键只需用于修饰只有一个参数的类构造函数, 它的作用是表明该构造函数是显示的, 而非隐式的, 跟它相对应的另一个关键字是implicit, 意思是隐藏的,类构造函数默认情况下即声明为implicit(隐式)。

    #include <iostream>
    using namespace std;
    
    class MyString{
    public:
        explicit MyString(int size){} //构造函数
        MyString(const char* s=NULL){}//构造函数2
    };
    
    int main(){
        MyString s1 = 'a';//这里原意是想用字符串"a"初始化s1,
                            //结果不小心将双引号""打成单引号''
        return 0;
    }

    可以看出,当构造函数前加了explicit关键字后,原本代码中发生隐式转换的地方现在在编译的时候不能通过,这样,也就防止了我们程序中可能出现的问题,记住,编译器是我们最好的朋友,我们尽可能的将代码中的隐患错误暴露给编译器,让它提醒我们以便及时去纠正我们的错误。

    需要注意的是,explicit 只能出现在构造函数的声明中。







    展开全文
  • 目标转换类型:最宽的数据类型为 2.用一种类型的表达式赋值给另一种类型的对象 目标转换类型:被赋值对象的类型 3.把一个表达式传递给一个函数,且表达式的类型与函数的形式参数的类型不相同 目标...
  • C++隐式类型转换

    2018-04-27 13:35:32
    C++隐式类型转换基本数据类型:bool,char,short,int,long,float,double,long doule其中它们的字节长度满足: (signed/unsigned)char&lt;=(unsigned)short&lt;=(unsigned)int&lt;=(unsigned)...
  • C++语言中,类型转换有两种方式,隐式类型转换和显示类型转换。今天我们就来聊一聊这些类型转换的具体意义和应用特点。1. 隐式类型转换在有隐式类型转换的表达式中,使用者不需要明确指定一个类型的对象该转换为...
  • 作者 |樱雨楼责编 | 屠敏出品 | CSDN(ID:CSDNnews)在上篇中,我们讨论了C++中与隐式类型转换相关的一些话题,而函数重载是与隐式类型转换相关的又一大重要话题,本篇将要讨论的内容即为隐式类型转换与函数重载之间...
  • c++中的隐式类型转换

    2019-05-26 19:05:43
    文章目录@[toc]概要发生转换的情形隐式类型转化规则 概要 类型转换,分为隐式类型转换和显示类型转化。这里主要讨论含无符号性的隐式类型转化。 发生转换的情形 赋值操作 示例: unsigned char c = -1; // c的结果...
  • C++中的隐式转换规则

    2020-03-10 21:44:40
    C++中的隐式转换规则与C中基本一致 在程序中的隐式转换是很安全的,不需要程序员操作(不同于强制类型转换),强制类型转换比较容易出错 C中隐式转换规则: C在以下四种情况时会进行隐式转换 1.算术表达式中,不同...
  • 文章目录强制类型转换转换结果:隐式类型转换(编译器默认进行的类型转换) 强制类型转换 转换结果: 成功转换:目标类型能够容纳目标值,结果不变 不成功转换:目标类型不能容纳目标值,结果产生截断 隐式类型转换...
  • C/C++中规定了一组内置类型的隐式类型转换规则,用于类型不一致的运算过程中。 算术运算,如 int + short + double 时,int和short的变量会隐式转换为double,再与double进行加法。 关系运算,如 if ( int < ...
  • 对于不同的操作,隐式转换规则会有所不同。下面针对不同种类的操作符分别介绍它们的隐式转换规则。 (1) 算术操作的类型转换 1) 如果其中一个操作数类型为long double,则另一个操作数也转换成long double。 2...
  • 隐式类型转换 系统自动进行,不需要开发人员介入。 显示类型转换: (强制类型转换C++强制类型转换分4种:这四种强制类型转换分别用于不同的目的,有不同的名字,提供更丰富的含义和功能,方便代码的维护与检查...
  • 1. 如果其中一个操作数为long double类型,则另一个操作数被转换为long double. 2. 否则,如果其中一个操作数为double, 则另一个操作数被转换为double. 3. 否则,如果其中一个操作数为float, 则另一个操作数也转换为...
  • C++ 隐式的类类型转换

    2018-02-01 15:30:17
      如果构造函数只接受一个实参,则它实际上定义了转换为此类类型隐式转换机制,有时我们把这种构造函数称作为转换构造函数。 实例 #include "stdafx.h" #include #include using namespace std; class ...
  • C++中存在转换构造函数机制,可通过一个实参调用的构造函数定义一条从构造函数的参数类型向类类型隐式转换规则。但需要注意的一点是编译器只会自动执行一步类型转换,多于一步时,编译器会报错。 在要求隐式转换...
  • 算术类型之间的隐式转换被设计得尽可能避免损失精度。 何时发生隐式类型转换: 在下面这些情况下,编译器会自动地转换运算对象类型: 在大多数表达式中,比int小的整型值首先提升为较大的整数类型 在条件中,非布尔...
  • 转换规则如下:(小范围转换为大范围)   下面通过一段代码来说明隐式类型转换的危害: #include &lt;iostream&gt; #include &lt;string&gt; using namespace std; int main() {  short s...
  • C/C++的数值类型隐式类型转换

    千次阅读 2015-11-10 11:14:19
    C/C++在二进制的基础上抽象了常用的数值类型:char, uchar, short, ushort, int, uint, long, ulong, float, double。...类型转换规则概括起来就两条. 1.先进行整型提升,再进行类型对齐。类型对齐时以size最大的
  • unsigned y = 1;...这里面有一个负数的补码问题和不同类型之间的隐式类型转换问题 首先负数的表示方法是负数的绝对值的二进制码取反再加1,-2的补码计算就是: 0000 0000 0000 0010->1111 1111...
  • 隐式类型转换,运算符重载
  • C++ 数值类型隐式转换

    2020-05-10 12:13:26
    隐式转换规则: 1.运算符的运算对象将转换成最宽的类型 2.当表达式中既有浮点类型也有整数类型时,整数值将转换成相应的浮点类型。 整型提升:bool, char, unsigned char, signed char, short --> int ->...
  • C++隐式转换的原则

    2018-07-28 20:46:02
    C++隐式转换的原则 基本数据类型 基本数据类型的转换以取值范围的作为转换基础(保证精度不丢失)。 隐式转换发生在从小-&gt;大的转换中。比如从char转换为int。 从int-》long。  自定义对象 子类对象...
  • 文章目录隐式转换什么是隐式转换C++隐式转换原则C++ 隐式转换发生条件隐式转换的风险explicit 关键字单引号与双引号this指针this指针的用处:this指针的使用:this指针程序示例:关于this指针的一个经典回答:类的this...
  • C++隐式转换

    千次阅读 2014-07-05 22:23:47
    因为发生了构造函数的隐式转换隐式转换这种规则允许用一个参数来初始化对象,这会调用类中带有一个参数的构造函数,这个参数也可以有默认值 只要有一个参数就行。 另外,加上 explicit 关键字,可以 消除...

空空如也

空空如也

1 2 3 4 5 ... 20
收藏数 25,389
精华内容 10,155
关键字:

c++隐式类型转换规则

c++ 订阅