重载决议:显式和初始化语法的作用是什么?

时间:2016-11-14 14:28:57

标签: c++ overload-resolution explicit

假设我有一个不可变的String类,如下所示:

#include <iostream>
#include <string>

class String
{
public:
    explicit String(const char *Value) : Size(std::strlen(Value)), Value(new char[Size + 1])
    {
        std::memcpy(this->Value, Value, Size + 1);
        std::cout << Value << ", novice." << Size << std::endl;
    }
    template <typename T, std::size_t N> String(const T (&Value)[N]) : Size(N - 1), Value(new char[N])
    {
        std::memcpy(this->Value, Value, N);
        std::cout << Value << ", expert." << Size << std::endl;
    }
    ~String()
    {
        delete[] Value;
    }
private:
    const std::size_t Size;
    char *Value;
};

void main()
{
    auto &s = "Welcome to C++";
    String string = s;
    String str {s};
    String st(s);
    return;
}

我想知道explicit扮演的角色以及初始化语法在选择构造函数重载时如何产生影响。

我理解,对于strst,我明确地调用了一个指向const char的构造函数,因此它们打印出来:

Welcome to C++, novice.
Welcome to C++, novice.

但我不明白为什么string

Welcome to C++, expert.

打印出来。请说明如何选择过载。

1 个答案:

答案 0 :(得分:1)

使用

String str {s};
String st(s);

explicit String(const char *Value)

选择指针过载的原因是因为它没有模板化。指针和数组构造函数都被认为是与s的精确匹配,因此它会有歧义,但由于数组构造函数是模板,因此它更少考虑匹配指针构造函数。即使您删除了explicit指针,仍然会选择重载。

现在用

String string = s;

explicit确实很重要,因为s不是String。这意味着编译器需要隐式地将其转换为1,因此它选择数组构造函数,因为它是完全匹配的,并且唯一可行的构造函数作为显式构造函数不能用于隐式转换。