构造函数显式关键字的使用 我试图理解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(); }