强制派生类以覆盖数据成员

Nic*_*mer 3 c++

我有一个虚类A的数据valval2.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明确设置的更好方法?

dav*_*igh 8

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是一个实现细节,并不打算以多态方式使用).