【问题标题】:Declare static, constant member in abstract base class, assign it to a value in derived class?在抽象基类中声明静态常量成员,将其分配给派生类中的值?
【发布时间】:2014-09-23 16:22:46
【问题描述】:

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

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

有没有办法获得所需的行为并同时声明 cstatic constsbsc

【问题讨论】:

  • 我不明白这个问题,如果您希望每个派生的 c 都有一个不同的值,那么它不能是静态的。如果需要修改,则不能为 const。如果问题只是访问,您不能在基类中将其设为私有并在必要时提供公共 getter/setter 吗?如果这不是你的意思,你能改写成一个具体的问题吗?
  • 它不需要修改,对于给定派生类的每个实例都是相同的值。但对于每个不同的派生类,它是不同的值。
  • 这听起来像是 X/Y 问题。你能告诉我们你为什么需要这个吗?
  • 如果每个派生类需要不同的值,则需要在内存中使用不同的位置,因此不能是静态的。您可以将其设为模板类并为每个派生具有不同的值,但它们实际上不会是相同的基类。 Mike 的答案尽可能接近,如果您不想存储它,可以使用具有常量返回类型的虚拟调度,或者您需要将该变量存储在特定于实例的变量中。

标签: c++ inheritance static constants


【解决方案1】:

你不能用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;}
};

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

【讨论】:

  • 是的,可以。我只是看起来像一个函数调用,只是为了返回一个在编译时已知并且永不改变的值是毫无意义的开销。
  • @Null:在编译时未知,因为它取决于调用它的对象的运行时类型。
  • 好点。我认为它在编译时是已知的,因为我只将基类指针分配给两个派生类之一的实例——如果我切换到不同的派生类,我会修改源代码并重新编译。我只有几个派生类的实例,所以我认为const 成员方法更适合我的目的——额外的空间需求并不是什么大问题。谢谢。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 2018-04-26
  • 2023-03-23
  • 2012-12-04
  • 1970-01-01
  • 1970-01-01
  • 2015-02-01
  • 1970-01-01
相关资源
最近更新 更多