C++中转换构造函数:将其它类型转换为当前类的类型

1.C++转换构造函数:将其它类型转换为当前类的类型

  • 在C/C++中,不同的数据类型之间可以相互转换。无需用户指明如何转换的称为自动类型转换(隐式类型转换),需要用户显式地指明如何转换的称为强制类型转换
        // 自动类型转换示例
        int a = 6;
        a = a + 3.12;  // 将小数转换为整数会抹掉小数点后面的数字
        // 强制类型转换示例
        int b = 100;
        int *p = &b;
        float *ptr = (float *)p;  // 将int *转换为float *只是简单地复制指针的值
    
  • 不管是自动类型转换还是强制类型转换,前提必须是编译器知道如何转换,例如,将小数转换为整数会抹掉小数点后面的数字,将int *转换为float *只是简单地复制指针的值,这些规则都是编译器内置的,我们并没有告诉编译器。总之,如果编译器不知道转换规则就不能转换,使用强制类型也无用,请看下面的例子:
        #include "iostream"
    
        using namespace std;
    
        // 如果编译器不知道转换规则就不能转换,使用强制类型也无用
        class complex{
            public:
                complex():m_real(0.0), m_img(0.0){}
                complex(double real, double img):m_real(real), m_img(img){}
            public:
                friend ostream & operator<< (ostream &out, const complex &c); // 友元函数
            private:
                double m_real;
                double m_img;
        };
    
        ostream & operator << (ostream &out, const complex &c){
            out << c.m_real << "+" << c.m_img << "i";
            return out;
        }
    
        int main(){
            complex a(10.0, 20.0);
            a = (complex) 25.5;  // 错误,转换失败
            return 0;
        }
    
  • 上面的例子中,25.5是实数,a是复数,将25.5赋值给a后,我们期望a的实部变为25.5,而虚部为0。但是,编译器并不知道这个转换规则,这超出了编译器的处理能力,所以转换失败,即使加上强制类型转换也无用。幸运的是,C++允许我们自定义类型转换规则,用户可以将其它类型转换为当前类类型,也可以将当前类类型转换为其它类型。这种自定义的类型转换规则只能以类的成员函数的形式出现。换句话说,这种转换规则只适用于类,本节先讲解如何将其它类型转换为当前类类型。

2.转换构造函数

  • 将其它类型转换为当前类类型需要借助转换构造函数(Conversion constructor)。转换构造函数也是一种构造函数,它遵循构造函数的一般规则,转换构造函数只有一个参数
        #include "iostream"
    
        using namespace std;
    
        /*---------------------------将其它类型转换为当前类的类型-------------------------------*/
    
        // 如果编译器不知道转换规则就不能转换,使用强制类型也无用
        class complex{
            public:
                complex():m_real(0.0), m_img(0.0){}
                complex(double real, double img):m_real(real), m_img(img){}
                complex(double real): m_real(real), m_img(0.0){}  // 转换构造函数,作用是将double类型的参数real转换成 complex类的对象,并将real作为复数的实部,将0作为复数的虚部
            public:
                friend ostream & operator<< (ostream &out, const complex &c); // 友元函数
            private:
                double m_real;
                double m_img;
        };
    
        ostream & operator << (ostream &out, const complex &c){
            out << c.m_real << " + " << c.m_img << "i";
            return out;
        }
    
        int main(){
            complex a(10.0, 20.0);
            cout << "a = " << a << endl;
            a = 25.5;  // 将赋值的过程转换成了函数调用的过程
            cout << "a = " << a << endl;
            return 0;
        }
    
  • 转换构造函数也是构造函数的一种,它除了可以用来将其它类型转换为当前类类型,还可以用来初始化对象,这是构造函数本来的意义。下面创建对象的方式是正确的:
        complex c1(23.1);  // 创建具名对象
        complex c2 = 24.3;  // 以拷贝的方式初始化对象,编译器先调用转换构造函数,将24.3转换为complex类型(创建一个complex类的匿名对象),然后再拷贝给c2。
        complex(3.21);  // 创建匿名对象
        c1 = complex(34.2);  // 创建一个匿名对象并将它赋值给 c1
    
  • 如果已经对+运算符进行了重载,使之能进行两个complex类对象的相加,那么下面的语句也是正确的:
        complex c1(15.6, 89.9);
        complex c2;
        c2 = c1 + 29.6;
        cout << c2 << endl;
    
  • 注意:为了获得目标类型,编译器会“不择手段”,会综合使用内置的转换规则和用户自定义的转换规则,并且会进行多级类型转换,例如:
    • 编译器会根据内置规则先将int转换为double,再根据用户自定义规则将double转换为complex(int --> double --> complex);
    • 编译器会根据内置规则先将char转换为int,再将int转换为double,最后根据用户自定义规则将double转换为complex(char --> int --> double --> complex)
          int main(){
              complex c1 = 100;  //int --> double --> complex
              cout << c1 << endl;
              c1 = 'A';  //char --> int --> double --> complex
              cout << c1 << endl;
              c1 = true;  //bool --> int --> double --> complex
              cout << c1 << endl;
              complex c2(25.8, 0.7);
              //假设已经重载了+运算符
              c1 = c2 + 'H' + true + 15;  //将char、bool、int都转换为complex类型再运算
              cout << c1 << endl;
              return 0;
          }
      

3.再谈构造函数

  • 构造函数的本意是在创建对象的时候初始化对象,编译器会根据传递的实参来匹配不同的(重载的)构造函数,几种形式的构造函数:
    • 默认构造函数: 就是编译器自动生成的构造函数,以complex类为例,它的原型为:
          complex();  // 没参数
      
    • 普通构造函数: 就是用户自定义的构造函数,以complex类为例,它的原型为:
          complex(double real, double img);  // 两个参数
      
    • 拷贝构造函数: 在以拷贝的方式初始化对象时调用,以complex类为例,它的原型为:
          complex(const complex &c);
      
    • 转换构造函数: 将其它类型转换为当前类类型时调用,以complex为例,它的原型为:
          complex(double real);  // 一个参数
      
  • 不管哪一种构造函数,都能够用来初始化对象,这是构造函数的本意。假设complex类定义了以上所有的构造函数,那么下面创建对象的方式都是正确的:
        complex c1();  // 调用complex()
        complex c2(10, 20);  // 调用complex(double real, double imag)
        complex c3(c2);  // 调用complex(const complex &c)
        complex c4(25.7);  // 调用complex(double real)
    
  • 除了在创建对象时初始化对象,其他情况下也会调用构造函数,例如:以拷贝的的方式初始化对象时会调用拷贝构造函数,将其它类型转换为当前类类型时会调用转换构造函数。这些在其他情况下调用的构造函数,就成了特殊的构造函数了。特殊的构造函数并不一定能体现出构造函数的本意。

4.对complex类的进一步精简

  • 上面的complex类中我们定义了三个构造函数,其中包括两个普通的构造函数和一个转换构造函数。其实,借助函数的默认参数,我们可以将这三个构造函数简化为一个,请看下面的代码:
        #include "iostream"
    
        using namespace std;
    
        /*---------------------------将其它类型转换为当前类的类型-------------------------------*/
    
        // 如果编译器不知道转换规则就不能转换,使用强制类型也无用
        class complex{
            public:
                complex(double real=0.0, double img=0.0):m_real(real), m_img(img){}
            public:
                friend ostream & operator<< (ostream &out, const complex &c); // 友元函数
            private:
                double m_real;
                double m_img;
        };
    
        ostream & operator << (ostream &out, const complex &c){
            out << c.m_real << " + " << c.m_img << "i";
            return out;
        }
    
        int main(){
            complex a(10.0, 20.0);  // 向构造函数传递2个实参,不使用默认参数
            cout << "a = " << a << endl;
            complex b(89.5);  // 向构造函数传递1个实参,使用1个默认参数
            cout << "b = " << b << endl;
            complex c;  // 不向构造函数传递实参,使用全部默认参数
            a = 25.5;  // 调用转换构造函数(向构造函数传递1个实参,使用1个默认参数)
            cout << "a = " << a << endl;
            return 0;
        }
    
  • 3
    点赞
  • 6
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
C++类型转换构造函数是一种特殊的构造函数,它允许将一个类型的对象转换为另一个类型的对象。类型转换构造函数通常用于实现隐式类型转换,使得在某些情况下可以自动地将一个类型转换为另一个类型。 下面是一个示例,演示了如何在C++定义和使用类型转换构造函数: ```cpp #include <iostream> class MyInt { public: MyInt(int value) : m_value(value) {} // 类型转换构造函数 MyInt(double value) : m_value(static_cast<int>(value)) {} int getValue() const { return m_value; } private: int m_value; }; int main() { MyInt myInt1 = 10; std::cout << "myInt1: " << myInt1.getValue() << std::endl; MyInt myInt2 = 3.14; std::cout << "myInt2: " << myInt2.getValue() << std::endl; return 0; } ``` 在上面的示例,我们定义了一个名为`MyInt`的,它有两个构造函数。第一个构造函数接受一个`int`类型的参数,用于初始化`m_value`成员变量。第二个构造函数接受一个`double`类型的参数,通过使用`static_cast`将其转换为`int`类型,并将结果赋值给`m_value`成员变量。 在`main`函数,我们分别使用`10`和`3.14`初始化了两个`MyInt`对象。由于存在类型转换构造函数,编译器会自动将`10`转换为`int`类型,并调用第一个构造函数进行对象的初始化。同样地,编译器会将`3.14`转换为`double`类型,并调用第二个构造函数进行对象的初始化。 输出结果为: ``` myInt1: 10 myInt2: 3 ```

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值