曲径通幽论坛

标题: 使用虚基类时的构造函数规则 [打印本页]

作者: easy    时间: 2013-12-14 20:35
标题: 使用虚基类时的构造函数规则
假设有下面的几个类定义:

[C++] 纯文本查看 复制代码
class A
{
int a;
public:
A(int n = 0) : a(n) {}
...
};
class B: public A
{
int b;
public:
B(int m = 0, int n = 0) : A(n), b(m)  {}
...
};
class C : public B
{
int c;
public:
C(int q = 0, int m = 0, int n = 0) : B(m, n), c(q) {}
...
};


上面代码中,几个类的声明与继承都是通常的情况。此时,C 类的构造函数只能调用 B 类的构造函数,而 B 类的构造函数只能调用 A 类的构造函数。这里,有一个信息向上传递的路径:C 类的构造函数将值 m 和 n 传递给 B 类的构造函数;而 B 类的构造函数又将值 n 传递给了 A 类的构造函数。

现在,假设 Worker 为一个虚基类,Singer 与 Waiter 都从其派生,而 SingingWaiter 则继承了 Singer 与 Waiter ,这是多重继承。如果给 Singingwaiter 添加如下一条构造函数:
  1. SingingWaiter(const Worker & wk, int p = 0, int v = other) : Waiter(wk, p), Singer(wk, v) {}
复制代码
在 Worker 为虚基类的这种情况下,上面第一个例子中所演示的信息自动传递将不起作用。假如可以传递,那么将有 Waiter 和 Singer 这两条不同的路径将 wk 传递给 Worker 对象,这样就会引起冲突。因此 C++ 规定,在基类为“虚”时,禁止信息通过中间类自动传递给基类。因此,参数 wk 中的信息不会传递给子对象 Waiter。但是,这么一来会跟一个规定相矛盾:编译器必须在构造对象之前构造基类对象组件。因此,在上述情况下,编译器会先直接跳去执行 Worker 的默认构造函数。

如果我们不希望默认构造函数来构造虚基类的对象,解决的办法是,显式地调用所需的基类构造函数。因此,改写上面的构造函数为:
SingingWaiter(const Worker & wk, int p = 0, int v = other) : Worker(wk), Waiter(wk, p), Singer(wk, v) {}

上述代码将显式地调用虚基类的构造函数 Work(const Work &) 。对于虚基类来说,这种用法是合法的,但对于非虚基类,则是非法的

总之,如果类有间接虚基类,那么除非只需使用该虚基类的默认构造函数,否则必须显式地调用该虚基类的某个构造函数。





欢迎光临 曲径通幽论坛 (http://www.groad.net/bbs/) Powered by Discuz! X3.2