构造函数显式关键字的使用 我试图理解C++中显式关键字的用法,并在上面看到这个问题。
然而,这里列出的例子(实际上是前两个答案)对于用法不是很清楚。比如说,构造函数显式关键字的使用 我试图理解C++中显式关键字的用法,并在上面看到这个问题。 ,c++,class,constructor,explicit,C++,Class,Constructor,Explicit,然而,这里列出的例子(实际上是前两个答案)对于用法不是很清楚。比如说, // classes example #include <iostream> using namespace std; class String { public: explicit String(int n); // allocate n bytes to the String object String(const char *p); // initializes object with c
// classes example
#include <iostream>
using namespace std;
class String {
public:
explicit String(int n); // allocate n bytes to the String object
String(const char *p); // initializes object with char *p
};
String::String(int n)
{
cout<<"Entered int section";
}
String::String(const char *p)
{
cout<<"Entered char section";
}
int main () {
String mystring('x');
return 0;
}
或
在这两种情况下,我将进入int部分。除非我指定了值的类型,否则它默认为int。即使我使用参数更具体,比如将一个声明为int,另一个声明为double,并且不使用显式的构造函数名并以这种方式调用它
String mystring(2.5);
还是这样
String mystring = 2.5;
它将始终默认为参数为double的构造函数。所以,我很难理解显式语法的真正用法。你能给我举一个不使用显式转换将是真正失败的例子吗?
explicit
旨在防止隐式转换。任何时候你都可以使用像String(foo)这样的东西代码>,这是一个显式转换,因此使用explicit
不会改变转换是否成功
因此,让我们来看一个涉及隐式转换的场景。让我们从您的字符串开始
类:
class String {
public:
explicit String(int n); // allocate n bytes to the String object
String(const char *p); // initializes object with char *p
};
然后,让我们定义一个函数,该函数接收类型为String
的参数(也可以是String const&
,但String
暂时可以):
构造函数允许从char const*
进行隐式转换,但只允许从int
进行显式转换。这意味着如果我打电话:
f("this is a string");
…编译器将生成代码,从字符串文本构造字符串对象,然后使用该String
对象调用f
但是,如果您试图呼叫:
f(2);
它将失败,因为接受int
参数的String
构造函数已标记为explicit
。这意味着,如果我想将int
转换为String
,我必须明确地执行以下操作:
f(String(2));
如果字符串(char const*)代码>构造函数也被标记为显式的,那么你也不能调用f(“这是一个字符串”)
——你必须使用f(字符串(“这是一个字符串”)代码>
但是,请注意,explicit
仅控制从某个类型foo
到您定义的类型的隐式转换。它对从其他类型隐式转换为explicit
构造函数所采用的类型没有影响。因此,采用类型int
的显式构造函数仍将采用浮点参数:
f(String(1.2))
…因为这涉及到从double
到int
的隐式转换,然后是从int
到String
的显式转换。如果要禁止从double
转换为String
,可以(例如)提供一个重载构造函数,该构造函数接受double
,但随后抛出:
String(double) { throw("Conversion from double not allowed"); }
现在将不会发生从double
到int
的隐式转换--double
将直接传递给您的ctor,而不进行转换
至于使用explicit
可以实现什么:使用explicit
的主要目的是防止编译本来可以编译的代码。当与重载结合使用时,隐式转换有时会导致一些非常奇怪的选择
使用转换运算符而不是构造函数来演示问题更容易(因为您只能使用一个类)。例如,让我们考虑一个很小的字符串类,它与人们理解的隐含转换的问题有很多相似之处:
class Foo {
std::string data;
public:
Foo(char const *s) : data(s) { }
Foo operator+(Foo const &other) { return (data + other.data).c_str(); }
operator char const *() { return data.c_str(); }
};
(我通过使用std::string
存储数据进行了欺骗,但如果我像他们那样存储char*
,并使用new
分配内存,情况也是如此)
现在,这使得类似这样的工作变得很好:
Foo a("a");
Foo b("b");
std::cout << a + b;
…试图减去两个String
对象的代码根本无法编译
同样的基本思想可以/确实适用于显式构造函数,但是演示它的代码会变得更长,因为我们通常需要至少两个不同的类。您是否希望String('x')
调用String(const char*)
'x'
是一个char
,而不是char
指针。无论如何,您只显示了字符串的显式构造,因此显式没有什么区别。尝试调用一个使用int
的字符串
的函数,它将不起作用,因为转换int
→ <无法隐式生成代码>字符串。String mystring='x'
@cpplearner我知道这一点,这就是为什么我表示我不使用explicit这个词。在您的示例中,您正在使用explicit@Biffen你能举例说明你的论点吗code@UnderDog哪个论点?如果你的意思是调用一个采用字符串的函数,那么请看Jerry Coffin的答案。我不确定你是否正确地将怀疑转换为int。如果我将一个双精度值传递给String对象,它将直接传递给希望双精度作为参数的构造函数(如果有),不考虑显式。@UnderDog:是和否。是,这是重载解析将选择的一个。但是,如果它被标记为显式,并且您试图使用它进行隐式转换,那么代码将无法编译。我理解这一点,我也同意这一点。但我的问题不是关于这个。我更感兴趣的是了解一些案例或示例代码,在这些案例或示例代码中,不使用显式会导致失败或不希望出现的行为,因为到目前为止,根据我所理解的解释,我认为使用显式没有多大价值。@UnderDog:我添加了一个示例。
String(double) { throw("Conversion from double not allowed"); }
class Foo {
std::string data;
public:
Foo(char const *s) : data(s) { }
Foo operator+(Foo const &other) { return (data + other.data).c_str(); }
operator char const *() { return data.c_str(); }
};
Foo a("a");
Foo b("b");
std::cout << a + b;
explicit operator char const *() { return data.c_str(); }