【发布时间】:2014-11-23 18:53:18
【问题描述】:
在 OS X 上使用 Xcode 5.1 编译以下代码时出现意外错误。 Apple LLVM 版本 5.1 (clang-503.0.40)(基于 LLVM 3.4svn)
class GrandParent
{
public:
GrandParent(int age) : m_age(age)
{
}
virtual ~GrandParent() {}
private:
GrandParent();
GrandParent(const GrandParent&);
const GrandParent& operator=(const GrandParent&);
int m_age;
};
class Parent1 : public virtual GrandParent
{
public:
Parent1(int age) : m_age(age)
{
}
virtual ~Parent1() {}
private:
Parent1();
Parent1(const Parent1&);
const Parent1& operator=(const Parent1&);
int m_age;
};
class Parent2 : public virtual GrandParent
{
public:
Parent2(int age) : m_age(age)
{
}
virtual ~Parent2() {}
private:
Parent2();
Parent2(const Parent2&);
const Parent2& operator=(const Parent2&);
int m_age;
};
class Child : public Parent1, public Parent2
{
public:
Child(int grandParentAge, int parent1Age, int parent2Age, int childAge) :
GrandParent(grandParentAge),
Parent1(parent1Age),
Parent2(parent2Age),
m_age(childAge)
{
}
virtual ~Child() {}
private:
Child();
Child(const Child&);
const Child& operator=(const Child&);
int m_age;
};
报告的错误是:
error: inherited virtual base class 'GrandParent' has private default constructor
Parent1(int age) : m_age(age)
^
note: declared private here
GrandParent();
^
error: inherited virtual base class 'GrandParent' has private default constructor
Parent2(int age) : m_age(age)
^
note: declared private here
GrandParent();
我的理解是,虚拟基类(GrandParent)的构造函数不会被继承自它的类(Parent1 或 Parent2)调用。相反,构造函数由具体类 (Child) 的构造函数调用。
这是正确的吗?
如果我为 GrandParent 提供默认构造函数,它可以编译。但是,如果我构造一个子对象:
Child child(80, 50, 49, 20);
检查一下,我可以看到:
Child) child = {
Parent1 = {
GrandParent = (m_age = 49)
m_age = 50
}
Parent2 = {
GrandParent = (m_age = 80)
m_age = 49
}
m_age = 20
所以使用 Parent1 时 GrandParent 的年龄是不正确的,但对于 Parent2 是正确的。
我是不是误会了什么?或者错误可能是编译器错误?
更新
如果我将 Parent1 的 ctor 更新为:
Parent1(int age) : GrandParent(100), m_age(age) { }
现在可以编译了。检查值显示:
(Child) child = {
Parent1 = {
GrandParent = (m_age = 49)
m_age = 50
}
Parent2 = {
GrandParent = (m_age = 80)
m_age = 49
}
m_age = 20
这显然是不对的。此外,修改后的代码在 Windows 上使用 VS 2013 Express 编译,检查值正确。
【问题讨论】:
-
不建议在
virtual像GrandParent这样的基类中包含数据成员 -
你的错误不在
Child;相反,它在Parent1和Parent2的定义中。 -
@PaulEvans:对
<iostream>-designers 这么说。 -
@KerrekSB:需要详细说明吗?
-
@ksl:好吧,你的班级
Parent1定义不明确。这与所有其他代码的存在无关。您可以删除一半的代码,但仍然有同样的问题。
标签: c++ constructor xcode5 virtual-inheritance ctor-initializer