C++ C++;静态常量成员重写

C++ C++;静态常量成员重写,c++,static-members,C++,Static Members,考虑以下几点 struct A { static const int X = 1; static void printX() {std::cout << "X " << X << std::endl; }; }; struct B: public A { static const int X = 2; }; int main(argc argv){ B b; b.printX(); } 结构A{

考虑以下几点

struct A {
    static const int X = 1;
    static void printX() {std::cout << "X " << X << std::endl; };
};

struct B: public A {
    static const int X = 2;
};

int main(argc argv){
    B b;
    b.printX();
}
结构A{ 静态常数int X=1;
静态void printX(){std::cout根据定义,您对静态成员所做的任何操作都将是“遮蔽”,而不是“覆盖”。您可以在“B”中重新实现“printX()”,但您不会真正重写该行为;因为这将使用阴影,所以该行为将完全取决于编译时,而不是运行时,类型。

简短回答:您不能

稍微长一点,更复杂一点的回答:嗯,也许你可以。用模板

#包括
模板结构A
{
静态常数int X=1;
静态void printX()
{ 

好的,我会继续玩…你想把这个嵌套到一层以上的深度。好的

#include <iostream>

template <int XX> struct T
{
    static const int X = XX;

    static void printX()
    {
        std::cout << "X=" << X << std::endl;
    }   
};

struct AA 
{
    static const int X = 1;

    /* all other members go here */
};

struct A : public AA, public T<AA::X>
{
    /* empty - put stuff in AA instead */
};

struct BB : public AA
{
    static const int X = 2;
};

struct B : public BB, public T<BB::X>
{
};

struct CC : public BB
{
    static const int X = 3;
};

struct C : public CC, public T<CC::X>
{
};

struct DD : public CC
{
    static const int X = 4;
};

struct D : public DD, public T<DD::X>
{
};

int main(int, char **)
{
    A a;
    B b;
    C c;
    D d;

    a.printX();
    b.printX();
    c.printX();
    d.printX();

    return 0;
}
#包括
模板结构
{
静态常数int X=XX;
静态void printX()
{

std::cout您将需要一个模板,并且要更改继承以使用模板,正如您将看到的。诀窍是使派生类是否有一个X来掩盖基类X

template<class C>
struct A {
    static const int X = 1;
    template<typename T>
    static int getX(decltype(T::X)*) 
        { return T::X; }
    template<typename T>
    static void getX(...)
        { return X; }
    static void printX()
        { std::cout << "X " << getX<C>(0) << std::endl; }
};

struct B: public A<B> {
    static const int X = 2;
};

struct B2: public A<B2> {
    // No X
};

int main(){
    B b;
    b.printX(); // Prints X 2
    B2 b2;
    b2.printX(); // Prints X 1
}
模板
结构A{
静态常数int X=1;
模板
静态int getX(decltype(T::X)*)
{返回T::X;}
模板
静态void getX(…)
{返回X;}
静态void printX()

{std::cout只需将X的值作为模板参数:

#include <iostream>

template<int XValue=1>
struct A {
        static const int X = XValue;
        static void printX() {std::cout << "X " << X << std::endl; };
};

template<int XValue=2>
struct B: public A<XValue> {
};

struct C: public B<3> {
};

int main(int, char**){
        B<> b;
        b.printX();
}
#包括
模板
结构A{
静态常数int X=XValue;

static void printX(){std::cout不使用
static
template
,我只使用常规常量属性和构造函数

例如:

#include <iostream>

struct A {
    A(const char* fn, const int X) : filename(fn), X(X) {};
    void print() { std::cout << "X = " << X << ", FN = " << filename << std::endl; };

  protected:
    const char* filename;
    const int X;
};

struct B : public A {
    B() : A("data.dat", 5) {};
};

int main(int, char **) {
    B b;
    b.print();
}

-现在,编译器的任务是优化这些常量。如果您不打算使用数千个对象
B
,那么让这些常量
成为静态的

可能是不可能的。您希望动态调度而不使用
虚拟的
,这是自相矛盾的(除非您手动重新实现对象系统)。来吧,要强制
b.printX()
打印2,只需将
X
替换为
printX()
定义中的2;-)不,我不想使用动态调度。我想使用静态成员常量。除了@ BaselestalyKevyy的评论之外,考虑一下:如何知道B的内容?如果你说“让B成为A的朋友”,那么,这只是一个糟糕的设计,而A仍然必须引用x作为b::x来获得b的x值。(事实上,你可以将A::X称为X只是一种方便。)@jpm,Exhipst
struct
s之间建立友谊的目的是什么?我认为OP可能会混淆这一区别,因为允许在该类的实例上调用类的静态。继承的下一步(B中的C)将杀死
printX()
当然可以,但坦率地说,如果你需要在更深层次上这样做,那么你的设计很糟糕,也许你应该重新考虑一下。当然,在这种设计中,你不能将B转换为a,因为它们不是直接从彼此派生的。但是,嘿……你赢了一些,你输了一些。直接从a派生B是必要的。是现在吗?哦……对不起,我不同意不要深入分析新的解决方案,因为它看起来很麻烦,而且也不合适。应该有一个更简单的解决方案!但是有点麻烦。顺便说一句,为什么要使用带星号的decltype(t::X)?为什么是指针,而不是值?+1很好的解决方案!(@OlegG指针是必需的,因此无论
X
的类型如何,伪参数
0
都可以工作)很好的解决方案,但我仍然认为设计很糟糕,Oleg需要坐下来重新思考,或者告诉我们他实际上在做什么。@JiveDadson:一般来说,由于继承的需要,在这个任务中使用模板不是很好的解决方案。您使用decltype()的想法这很好,但最好为当前类型值发明一些类似的方法。然后我们将只编写cout@OlegG我的第一次尝试尝试尝试定义类型D,以便您可以在基类中编写D::X,但我的编译器(VC++2012)拒绝它。我认为我是对的,它是错的,但我不喜欢发布不编译的答案。我更改了代码,使其使用getX(0),它不如D::X漂亮,但它确实工作。
#include <iostream>

struct A {
    A(const char* fn, const int X) : filename(fn), X(X) {};
    void print() { std::cout << "X = " << X << ", FN = " << filename << std::endl; };

  protected:
    const char* filename;
    const int X;
};

struct B : public A {
    B() : A("data.dat", 5) {};
};

int main(int, char **) {
    B b;
    b.print();
}
X = 5, FN = data.dat