2014-09-23 29 views
1

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

在上面的代码sbscstatic const会员我想要的,但他们的问题是基类A没有他们的知识。基类成员c正在做我想要的,但不是static const根据需要(我做了c一个protected成员,以便它不能被修改,但如果我可以宣布它const那么它可以是public)。此代码具有从c所需的行为:

  1. 我可以得到鲜明的值c从使用基类指针每个派生类。
  2. c是有效的,因为它是protected,我没有提供setter功能。

然而,c是不是真的不断在它不是const,它不是那么static每个实例有它的一个不必要的副本。

有没有办法得到想要的行为,还宣布cstatic constsbsc

+0

我不明白这个问题,如果你想为每个派生c一个不同的值,那么它不能是静态的。如果需要修改,那么它不能是const。如果关注只是访问,那么你可以在基类中将其隐藏起来,并在必要时提供公共getter/setter?如果这不是你的意思,你能否改写成具体的问题? – skimon 2014-09-23 16:36:58

+0

它不需要修改,并且对于给定的派生类的每个实例它都是相同的值。但对于每个不同的派生类来说它是一个不同的值。 – Null 2014-09-23 16:39:58

+0

这听起来像是一个X/Y问题。你能告诉我们为什么你需要这个吗? – Borgleader 2014-09-23 16:40:33

回答

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

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

+0

是的,这将工作。我只是看起来像一个函数调用,只是为了返回一个在编译时已知的值,并且从不改变是无意义的开销。 – Null 2014-09-23 16:50:54

+0

@Null:在编译时不知道,因为它取决于它所调用的对象的运行时类型。 – 2014-09-23 16:51:58

+0

好点。我认为它在编译时是已知的,因为我只将基类指针赋值给两个派生类之一的实例 - 如果我切换到不同的派生类,则修改源并重新编译。我只有几个派生类的实例,所以我认为'const'成员方法对我的目的更好 - 额外的空间需求并不是什么大问题。谢谢。 – Null 2014-09-23 17:04:01

相关问题