从成员初始化器列表中调用基方法
Calling base methods from member initializer list
从成员初始化列表中调用非虚基方法安全吗?和虚拟?
在所有基类初始化之前调用任何成员函数(虚拟或非虚拟)是不安全。下面是标准 ([class.base.init]§16) 中给出的示例:
class A {
public:
A(int);
};
class B : public A {
int j;
public:
int f();
B() : A(f()), // undefined behavior: calls member function but base A not yet initialized
j(f()) { } // well-defined: bases are all initialized
};
class C {
public:
C(int);
};
class D : public B, C {
int i;
public:
D() : C(f()), // undefined behavior: calls member function but base C not yet initialized
i(f()) { } // well-defined: bases are all initialized
};
还有subtle cases.
正如我在评论中所说:
派生 class 的初始化列表中首先初始化的是基 class。明确地看起来像这样:
class A{ ... };
class B : public A {
int x, y;
B() : A{}, x{...}, y{...} {
...
}
};
因此,在初始化 x
和 y
时,您可以调用 A
的任何 非虚拟 方法,因为它已经被构建。
问题的第二部分与virtual
ness没有太大关系-它只是一个问题,您是否可以在构造函数中调用成员函数。答案是 是的,但是 - 你需要确保你没有使用对象的任何未初始化部分。
例如
struct Base {
virtual int f(int i) = 0;
};
struct Derived : public Base {
int x;
int y;
virtual int f(int i) override { return i; }
Derived(int i) : Base{}, x{f(i)}, y{f(x)} {}
};
可以,但是写... Derived(int i) : Base{}, x{f(y)}, y{f(i)} ...
就不行了。
从成员初始化列表中调用非虚基方法安全吗?和虚拟?
在所有基类初始化之前调用任何成员函数(虚拟或非虚拟)是不安全。下面是标准 ([class.base.init]§16) 中给出的示例:
class A {
public:
A(int);
};
class B : public A {
int j;
public:
int f();
B() : A(f()), // undefined behavior: calls member function but base A not yet initialized
j(f()) { } // well-defined: bases are all initialized
};
class C {
public:
C(int);
};
class D : public B, C {
int i;
public:
D() : C(f()), // undefined behavior: calls member function but base C not yet initialized
i(f()) { } // well-defined: bases are all initialized
};
还有subtle cases.
正如我在评论中所说:
派生 class 的初始化列表中首先初始化的是基 class。明确地看起来像这样:
class A{ ... };
class B : public A {
int x, y;
B() : A{}, x{...}, y{...} {
...
}
};
因此,在初始化 x
和 y
时,您可以调用 A
的任何 非虚拟 方法,因为它已经被构建。
问题的第二部分与virtual
ness没有太大关系-它只是一个问题,您是否可以在构造函数中调用成员函数。答案是 是的,但是 - 你需要确保你没有使用对象的任何未初始化部分。
例如
struct Base {
virtual int f(int i) = 0;
};
struct Derived : public Base {
int x;
int y;
virtual int f(int i) override { return i; }
Derived(int i) : Base{}, x{f(i)}, y{f(x)} {}
};
可以,但是写... Derived(int i) : Base{}, x{f(y)}, y{f(i)} ...
就不行了。