显式关键字在C++中意味着什么?


当前回答

在C++中,只有一个必需参数的构造函数被视为隐式转换函数。它将参数类型转换为类类型。这是否是一件好事取决于构造函数的语义。

例如,如果您有一个带有构造函数string(constchar*s)的字符串类,这可能正是您想要的。您可以将constchar*传递给需要String的函数,编译器将自动为您构造一个临时String对象。

另一方面,如果您有一个缓冲类,其构造函数buffer(int size)以字节为单位表示缓冲区的大小,那么您可能不希望编译器悄悄地将int转换为Buffers。为了防止这种情况,可以使用显式关键字声明构造函数:

class Buffer { explicit Buffer(int size); ... }

这样,

void useBuffer(Buffer& buf);
useBuffer(4);

成为编译时错误。如果要传递临时缓冲区对象,必须显式执行以下操作:

useBuffer(Buffer(4));

总之,如果单参数构造函数将参数转换为类的对象,则可能不希望使用显式关键字。但是,如果您有一个构造函数恰好接受一个参数,那么应该将其声明为显式的,以防止编译器意外地进行转换。

其他回答

在C++中,只有一个必需参数的构造函数被视为隐式转换函数。它将参数类型转换为类类型。这是否是一件好事取决于构造函数的语义。

例如,如果您有一个带有构造函数string(constchar*s)的字符串类,这可能正是您想要的。您可以将constchar*传递给需要String的函数,编译器将自动为您构造一个临时String对象。

另一方面,如果您有一个缓冲类,其构造函数buffer(int size)以字节为单位表示缓冲区的大小,那么您可能不希望编译器悄悄地将int转换为Buffers。为了防止这种情况,可以使用显式关键字声明构造函数:

class Buffer { explicit Buffer(int size); ... }

这样,

void useBuffer(Buffer& buf);
useBuffer(4);

成为编译时错误。如果要传递临时缓冲区对象,必须显式执行以下操作:

useBuffer(Buffer(4));

总之,如果单参数构造函数将参数转换为类的对象,则可能不希望使用显式关键字。但是,如果您有一个构造函数恰好接受一个参数,那么应该将其声明为显式的,以防止编译器意外地进行转换。

使单参数构造函数(包括具有arg2、arg3、…的默认值的构造函数)如前所述始终是一种良好的编码实践。就像C++一样:如果你不这样做,你会希望你这样做。。。

类的另一个好做法是将副本构造和赋值设为私有(也就是禁用它),除非你真的需要实现它。这避免了在使用C++默认为你创建的方法时,指针的最终副本。另一种方法是从boost::noncopyable派生。

假设您有一个类String:

class String {
public:
    String(int n); // allocate n bytes to the String object
    String(const char *p); // initializes object with char *p
};

现在,如果您尝试:

String mystring = 'x';

字符“x”将隐式转换为int,然后将调用String(int)构造函数。但是,这不是用户可能想要的。因此,为了防止出现这种情况,我们应明确定义构造函数:

class String {
public:
    explicit String (int n); //allocate n bytes
    String(const char *p); // initialize sobject with string p
};

显式关键字将构造函数转换为非转换构造函数。因此,代码不太容易出错。

显式关键字可用于强制显式调用构造函数。

class C {
public:
    explicit C() =default;
};

int main() {
    C c;
    return 0;
}

构造函数C()前面的显式关键字告诉编译器只允许显式调用此构造函数。

显式关键字也可以在用户定义的类型转换运算符中使用:

class C{
public:
    explicit inline operator bool() const {
        return true;
    }
};

int main() {
    C c;
    bool b = static_cast<bool>(c);
    return 0;
}

这里,显式关键字只强制显式强制转换为有效,因此bool b=c;在这种情况下将是无效的强制转换。在类似于这些显式关键字的情况下,可以帮助程序员避免隐式、非预期的强制转换。这种用法已在C++11中标准化。