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

时间:2014-09-23 16:22:46

标签: c++ inheritance static const

我有一个抽象基类和一对从这个基类派生的类。我想介绍一个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;
}

在上面的代码中,sbsc是我想要的static const成员,但问题是基类A不知道它们。基类成员c正在按我的意愿行事,但不是static const所需(我已c成为protected成员,因此无法修改,但如果我可以声明const然后它可以是public)。此代码具有c

所需的行为
  1. 我可以使用基类指针从每个派生类中获取c的不同值。
  2. c实际上是常量,因为它是protected而我没有提供setter函数。
  3. 但是,c不是真正的常量,因为它不是const而且它不是static所以每个实例都有一个不必要的副本它的。

    有没有办法获得所需的行为,并且cstatic const sbsc一起声明{{1}}?

1 个答案:

答案 0 :(得分:4)

您无法在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) {}
};

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

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;}
};

这两个选项都符合您的要求;一个具有访问虚拟函数调用的成本,而另一个具有每个对象变量的成本。您必须决定哪种费用更适合您的需求。