显式关键字在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));
总之,如果单参数构造函数将参数转换为类的对象,则可能不希望使用显式关键字。但是,如果您有一个构造函数恰好接受一个参数,那么应该将其声明为显式的,以防止编译器意外地进行转换。
其他回答
使单参数构造函数(包括具有arg2、arg3、…的默认值的构造函数)如前所述始终是一种良好的编码实践。就像C++一样:如果你不这样做,你会希望你这样做。。。
类的另一个好做法是将副本构造和赋值设为私有(也就是禁用它),除非你真的需要实现它。这避免了在使用C++默认为你创建的方法时,指针的最终副本。另一种方法是从boost::noncopyable派生。
显式关键字将构造函数转换为非转换构造函数。因此,代码不太容易出错。
其他答案缺少一个重要因素,我将在这里提及。
除了“delete”关键字,“explicit”允许您控制编译器生成特殊成员函数的方式——默认构造函数、复制构造函数、复制赋值运算符、析构函数、移动构造函数和移动赋值。
参考https://learn.microsoft.com/en-us/cpp/cpp/explicitly-defaulted-and-deleted-functions
这个答案是关于带/不带显式构造函数的对象创建的,因为其他答案中没有涉及它。
考虑以下没有显式构造函数的类:
class Foo
{
public:
Foo(int x) : m_x(x)
{
}
private:
int m_x;
};
Foo类的对象可以通过两种方式创建:
Foo bar1(10);
Foo bar2 = 20;
根据实现的不同,实例化类Foo的第二种方式可能会令人困惑,或者不是程序员想要的。将显式关键字前缀到构造函数将在Foobar2=20;处生成编译器错误;。
通常最好将单参数构造函数声明为显式的,除非您的实现明确禁止。
还请注意,具有
所有参数的默认参数,或第二个参数的默认参数
都可以用作单参数构造函数。因此,您可能希望将这些也明确化。
例如,如果您正在创建一个函子(请查看此答案中声明的“add_x”结构),那么您可能会故意不想使单参数构造函数显式。在这种情况下,创建add_x add30=30的对象;可能会有意义。
这里有一篇关于显式构造函数的好文章。
显式关键字可用于强制显式调用构造函数。
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中标准化。
推荐文章
- 为什么这个结合赋值和相等检查的if语句返回true?
- cplusplus.com给出的错误、误解或坏建议是什么?
- 找出质数最快的算法是什么?
- c++枚举类可以有方法吗?
- 格式化IO函数(*printf / *scanf)中的转换说明符%i和%d之间的区别是什么?
- 将析构函数设为私有有什么用?
- main()中的Return语句vs exit()
- 为什么c#不提供c++风格的'friend'关键字?
- 在函数的签名中添加关键字
- 我可以调用重载构造函数从另一个构造函数的同类在c# ?
- 我如何在Visual Studio中预处理后看到C/ c++源文件?
- 为什么在标准容器中使用std::auto_ptr<>是错误的?
- 用比较double和0
- 保护可执行文件不受逆向工程的影响?
- 在c++中字符串前面的“L”是什么意思?