error: base class 'A1' has private copy constructor

error: base class 'A1' has private copy constructor

在 windows 平台上使用 Clang 3.7

见以下代码:

class A1
{
public:
    A1(char* name){}
    virtual ~A1() {}
private:
    A1(const A1&) {}
};

class B1 : public A1
{
public:
    B1(): A1(""){}
};

我收到以下错误:

 MyFile(31): 8: error: base class 'A1' has private copy constructor
         B1(): A1(""){}
               ^
 MyFile(25): 2: note: declared private here
         A1(const A1&) {}
         ^

制作A1拷贝构造函数public,错误消除!

这里发生了什么?

注意:通过更改(我应该这样做)

A1(const char* name)

我没有收到任何错误,并且全部按预期编译

我想这只是诊断信息生成方式的人工制品。

  • 首先,查找会尝试找到一个构造函数来匹配您的 "call"(这不是调用,而是其他)
  • 如您所知,选择 char* 的 ctor 不匹配
  • 唯一的其他候选人是 private
  • 编译器会尝试查看它是否可以根据您的 "" 参数实例化一个临时 A1 以使其工作
  • 在这样做时,它再次能找到的是private个构造函数
  • 编译器决定在做任何其他事情之前对此进行抱怨

有人可能认为这是实施质量问题。

有趣的是,GCC 6.1.0 (even in pedantic C++14 mode) compiles your code as originally written,只吐出一个警告字面转换失败。

您不能使用字符串文字调用构造函数 A1(char* name),因为字符串文字不能转换为 char*(这种弃用的转换在 c++11 之前确实存在)。或者更确切地说,调用构造函数的程序格式错误,并且允许实现拒绝编译。

因此,重载解决方案寻找其他替代方案。具有相同数量参数的唯一其他潜在替代方案是复制构造函数。

无论出于何种原因,clang 似乎更喜欢从字符串文字到 A1 的隐式转换,从而创建一个可用于复制初始化的临时文件,而不是使用文字的直接构造。此行为会导致令人困惑的编译错误。

两种选择都是错误的,clang 对此发出了适当的警告:warning: ISO C++11 does not allow conversion from string literal to 'char *' [-Wwritable-strings]。如果您将标准模式设置为早于 c++11(在这种情况下,程序将是格式良好的,即使它确实使用了不推荐使用的转换),程序确实可以编译。有趣的是,如果我们不允许转换,那么程序即使在当前标准模式下也能编译:

class A1
{
public:
    explicit A1(char* name){} // note the explicit
    virtual ~A1() {}
private:
    A1(const A1&) {}
};

G++ 的行为不同,您的程序编译正常(当然有适当的警告)。这两个编译器似乎都符合这方面的标准。

故事的寓意:始终阅读警告。在这种情况下,警告非常清楚,也很容易解决,而同样的错误间接导致了错误,对解决错误没有帮助。