C++——单参构造函数类的强制类型转换

C++允许指定在类和基本类型之间进行转换的方式。首先,任何接受唯一一个参数的构造函数都可被用作转换函数,将类型与改参数相同的值转换为类

class B;

B(double a); //OK
B(double a,int b); //NO
B(double a, int) //NO
B(double a, int = 0); //OK
B(double a, int b = 10) //OK

在构造函数前面用explicit修饰,限定必须显式的进行强制转换

explicit B(double a, int = 0); //OK

一些使用

#include <iostream>

using namespace std;

class A
{
public:
    double a;
    A(double a)
    {
        this->a = a;
    }
};

class B
{
public:
    int b;
    explicit B(double b)
    {
        this->b = b;
    }
};
int main()
{
    A a_ = 20.4;
    cout << a_.a << endl;
    //事实上这里编译器会给出警告
    //Clang-Tidy: Single-argument constructors must be marked explicit to avoid unintentional implicit conversions
    //必须将单参数构造函数标记为显式,以避免无意的隐式转换
    //《C++ Primer Plus》也是给出这样的解释,所以,尽量在单参构造函数标记为显式

    //B b_ = 30.4; //error: No viable conversion from 'double' to 'B' 从'double'到'A'没有可行的转换
    //在explicit 修饰的作用下,仍然可以显式的转换

    //构造函数注意,这种显式初始化只有在构造函数的形参是一个参数时才起作用
    B b_1 = B(30.4); //or B b_1 = B{ 30.4 }
    cout << b_1.b << endl;

    //强制转换,注意,这种强制转换只有在构造函数的形参是一个参数时才起作用
    B b_2 = (B) 30.4;
    cout << b_2.b << endl;

    B b_3 = (B)30;
    cout << b_3.b << endl;

    return  0;
}

只有在声明中使用了关键字explicit才不能隐式的强制转换,否则,隐式的强制转换还可以用于以下

1.将类对象初始化

B b_ = {20.4};

2.将单参类型赋值给类对象

B b_;

b_ =  20.4;

3.将单参类型传递给接受类对象为参数的函数时

void func (B b,int a);

func(20.4, 3);

4.返回值为类的函数的函数试图返回单参类型时

B func(void)     return 20.4;

5.在上述任意的一种情况下,使用可转换为单参类型的内置类型

int 可以转换为double

B b_ = 10; //OK

 使用转换函数时注意的问题

不要出现二义性

long d = a_; //error :Conversion from 'A' to 'long' is ambiguous 从'A'到'long'的转换是不明确的

这时候编译器不知道将调用哪个构造函数,因为int 可以转换为long 同样的double 也可以转换为long类型,编译器不会替你做出这个决定

可以把转换函数写成一个类方法,而不是一个类内的转换函数

原则上尽量使用显式的转换函数来避免不必要的错误,应谨慎的使用隐式转换函数。通常,最好选择仅在被显示调用时才会执行的函数

#include <iostream>

using namespace std;

class A
{
public:
    double a;
    A(double a)
    {
        this->a = a;
    }
    operator double() const
    {
        return (int) this->a;
    }
    int A_to_int() const
    {
       return (int) this->a;
    }
};

int main()
{
    A a = 10.4;
    int t = a;
    cout << "a.a(double) is " << a.a <<endl;
    cout << "but to int is " << t << endl;  //隐式转换
    cout << "use class function to int is " << a.A_to_int(); //调用非转换函数的类方法
    return 0;
}

  • 1
    点赞
  • 3
    收藏
    觉得还不错? 一键收藏
  • 3
    评论
### 回答1: 我可以解释explicit构造函数的用法。 explicit构造函数C++中的一种特殊构造函数,它可以防止的实例被隐式转换,从而避免出现错误。它通常被定义为一个具有const限定符的成员函数,这意味着它不能修改的成员变量。 ### 回答2: 在C++中,构造函数被用于创建对象并初始化其成员变量。然而,有时我们可能希望禁止隐式地将某个的一个参数型转换为该的对象型,这时就可以使用explicit关键字来声明构造函数。 当我们使用explicit关键字声明一个构造函数时,它将不再能够进行隐式型转换。只有在显式地调用构造函数时,才能使用该构造函数创建一个对象。 explicit关键字的使用可以避免一些潜在的问题和错误的发生。它可以防止编译器隐式地将一个参数型转换为对象型,以免引发意想不到的结果。 举个例子,假设有一个A,其中有一个带有一个int参数的构造函数。如果我们不使用explicit关键字来声明该构造函数,那么在编译器看来,一个int型的变量可以被自动转换为一个A型的对象。这种隐式转换可能会导致意想不到的结果和错误的发生。 但是如果我们使用explicit关键字来声明该构造函数,那么编译器将不再允许隐式转换,只能通过显式调用构造函数来创建对象。 总之,explicit关键字用于禁止隐式地将一个参数型转换为对象型。它可以避免潜在的问题和错误,使代码更加可靠和健壮。 ### 回答3: 在C++中,构造函数Constructor)是一种特殊型的成员函数,用于在创建对象时初始化对象的数据成员。当我们定义一个时,可以定义一个或多个构造函数来满足不同的对象创建需求。其中,explicit是一个关键字,用于修饰构造函数explicit关键字的作用是防止隐式转换,它只能用于单参构造函数(即只有一个参数的构造函数)。当构造函数声明为explicit时,禁止编译器通过隐式转换将该参数型转换成对应的型。可以通过显式方式调用构造函数进行对象的创建和转换。 举个例子,假设有一个A,其中定义了一个单参构造函数A(int n),同时使用了explicit关键字进行修饰。如果没有explicit关键字修饰,则可以进行隐式转换,比如可以使用A对象去初始化一个int型的变量。但是,如果使用explicit修饰之后,编译器将不再允许隐式转换,只能通过显式方式进行构造和转换。 这种explicit用法可以避免一些不必要的型转换带来的错误和混淆,能够增加程序的型安全性。此外,explicit关键字还可以用于拒绝编译器进行多次隐式转换,因为如果构造函数没有使用explicit关键字修饰,编译器可能会进行多次自动型转换,导致程序的行为变得复杂和难以理解。 总结来说,当我们在定义构造函数时,如果希望限制使用隐式转换创建对象的情况,就可以使用explicit关键字对构造函数进行修饰,以保证程序的可读性和型安全性。

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值