我有一个虚拟类 A
,其中包含数据 val
和 val2
。 val
由 A
设置,但 val2
应该由 A
的 child 设置(基于值val
)。我想强制每个派生类设置val2
。以下
#include<iostream>
class A {
public:
A(): val(1), val2(getVal2())
{};
int val;
int val2;
protected:
virtual int getVal2() = 0;
};
class B: public A {
protected:
virtual int getVal2() { return 2*val; };
};
int main(){
B b;
std::cout << b.val2 << std::endl;
}
不 是否工作,因为 A
的构造函数调用了一个当时尚未定义的函数 (getVal2
):
/tmp/cc7x20z3.o: In function `A::A()':
test9.cpp:(.text._ZN1AC2Ev[_ZN1AC5Ev]+0x1f): undefined reference to `A::getVal2()'
collect2: error: ld returned 1 exit status
强制派生类显式设置 val2
的更好方法是什么?
最佳答案
将 val2
作为基类构造函数中的参数(不要使用默认构造函数):
class A
{
public:
A(int _val2) : val(1), val2(_val2) {};
A() = delete; //for clarity, not required as it is implicitly deleted
//...
int val;
int val2;
};
这需要派生类在它们的构造函数中设置val2
:
struct B : public A
{
B() : A(0) {} //A must be initialized, thus val2 is set in any case
// ...
};
不要尝试访问基类构造函数中的纯虚成员:它们尚未构造,因此尚不可访问;这会产生 undefined behaviour .
编辑:从评论来看,问题似乎实际上比 OP 中描述的更复杂。即:val
应在派生类构造函数初始化列表中可用(并且不应是静态的)。
我想到的最简洁的解决方案(其他人请参阅评论)是引入另一个基类并派生virtual
:
struct Abase
{
Abase() : val(1) {}
int val;
};
struct A : virtual Abase
{
A(int _val2) : val2(_val2) {}
int val2;
};
struct B : virtual A
{
B() : /* Abase() is called implicitly here, */ A(2*val){}
//^^^^^ now val is correctly initialized.
};
DEMO .
此外,您可以考虑继承 protected
(因为至少 Abase
是一个实现细节,并不意味着要以多态方式使用)。
关于c++ - 强制派生类覆盖数据成员,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/30848517/