在抽象基类中声明静态常量成员,并将其分配给派生类中的值?

Nul*_*ull 2 c++ inheritance static constants

我有一个抽象基类和一对从该基类派生的类。我想引入一个static const成员,该成员在两个派生类之间具有不同的值,但对于给定派生类的所有实例具有相同的值。

我的代码使用分配给两个派生类之一的实例的基类指针,以便我可以通过更改基类指针分配的内容来轻松地在派生类之间切换。我希望能够以类似的方式使用基类获取派生类的常量值,以便我可以轻松地在两个类之间切换。期望的行为看起来像这样:

#include <iostream>
using namespace std;

// Abstract base class
class A {
    protected:
    int c; // this is really a constant and should also be static
    public:
    static int s;
    int get_c() const {
        return this->c;
    }
    virtual int foo() = 0; // makes this class abstract
};

class B : public A {
    public:
    static const int sb = 10;
    B() {
        this->c = 1;
    }
    int foo() {
        return -1;
    }
};

class C : public A {
    public:
    static const int sc = 20;
    C() {
        this->c = 2;
    }
    int foo() {
        return -2;
    }
};

int main() {
    B btest;
    C ctest;

    A *ptr = &btest; // pointer to instance of B
    //cout << ptr->c << endl; // would fail compilation (c is protected)
    cout << "B's c = " << ptr->get_c() << endl;
    cout << "B's foo() returns " << ptr->foo() << endl;
    cout << "Accessing B's static const member: " << B::sb << endl;

    ptr = &ctest; // pointer to instance of C
    //cout << ptr->c << endl; // would fail compilation (c is protected)
    cout << "C's c = " << ptr->get_c() << endl;
    cout << "C's foo() returns " << ptr->foo() << endl;
    cout << "Accessing C's static const member: " << C::sc << endl;

    return 0;
}
Run Code Online (Sandbox Code Playgroud)

在上面的代码中sb, 和scstatic const我想要的成员,但它们的问题是基类A不了解它们。基类成员c正在做我想做的事情,但没有达到static const预期目的(我已经创建了c一个protected成员,以便它不能被修改,但如果我可以声明它,那么const它就可以public)。此代码具有以下期望的行为c

  1. c我可以使用基类指针从每个派生类获取不同的值。
  2. c实际上是恒定的,因为它是恒定的protected,并且我没有提供设置函数。

然而,它c并不是真正恒定的,因为它不是,const所以static每个实例都有它的不必要的副本。

有没有办法获得所需的行为并cstatic constlikesb和进行声明sc

Mik*_*our 6

您不能使用A;中的静态变量来实现这一点 这对于 的所有子类型都是通用的A,因此您无法为每个子类型获得不同的值。由于基类指针后面的对象的动态类型仅在运行时才知道,因此您需要一个运行时机制来从中获取值。

这可以使用每个对象的变量,const如果您在构造函数中初始化它,则可以:

class A {
    // ...
    const int c;
    A(int c) : c(c) {}
};

class B : public A {
    // ...
    B() : A(1) {}
};

class C : public A {
    // ...
    C() : A(2) {}
};
Run Code Online (Sandbox Code Playgroud)

或每个子类重写以返回不同值的虚函数:

class A {
    // ...
    int get_c() const = 0;
};

class B : public A {
    // ...
    int get_c() const {return 1;}
};

class C : public A {
    // ...
    int get_c() const {return 2;}
};
Run Code Online (Sandbox Code Playgroud)

两种选择都满足您的要求;一种是访问时虚拟函数调用的成本,另一种是每个对象变量的成本。您必须决定哪种成本更适合您的需求。