我有一个虚类A的数据val和val2.val由...设置A,但val2应该由子项设置A(基于值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;
}
Run Code Online (Sandbox Code Playgroud)
并没有因为构造工作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
Run Code Online (Sandbox Code Playgroud)
什么是强制派生类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;
};
Run Code Online (Sandbox Code Playgroud)
这需要val2在其构造函数中设置派生类:
struct B : public A
{
B() : A(0) {} //A must be initialized, thus val2 is set in any case
// ...
};
Run Code Online (Sandbox Code Playgroud)
不要尝试访问基类构造函数中的纯虚拟成员:它们尚未构造,因此尚不可访问; 这会产生未定义的行为.
编辑:从评论看来,似乎问题实际上比OP中描述的更复杂.即:val应该可以在派生类构造函数初始化列表中使用(并且不应该是静态的).
Imo我提出的最干净的解决方案(对于其他人看到的评论)是引入另一个基类并派生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.
};
Run Code Online (Sandbox Code Playgroud)
演示.
此外,您可以考虑继承protected(因为至少Abase是一个实现细节,并不打算以多态方式使用).
| 归档时间: |
|
| 查看次数: |
116 次 |
| 最近记录: |