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++ 的行为不同,您的程序编译正常(当然有适当的警告)。这两个编译器似乎都符合这方面的标准。
故事的寓意:始终阅读警告。在这种情况下,警告非常清楚,也很容易解决,而同样的错误间接导致了错误,对解决错误没有帮助。
在 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++ 的行为不同,您的程序编译正常(当然有适当的警告)。这两个编译器似乎都符合这方面的标准。
故事的寓意:始终阅读警告。在这种情况下,警告非常清楚,也很容易解决,而同样的错误间接导致了错误,对解决错误没有帮助。