C ++静态const成员覆盖

时间:2012-11-12 07:59:32

标签: 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();
}

如何强制b.printX()打印值2? - 常量和方法 - 必须是静态的。因此,虚拟方法并不合适。

对于那些认为自己比我更了解自己的任务并且想要重新思考我的人,我会解释我努力的最终目标:) 想象一下基于静态常量集的行为的类。实现具有不同常量集并因此具有不同行为的子类的最简单方法是使用特定的常量值集从前一个类派生类。可以使用虚拟检查来解决该任务。原因可能,毫无疑问。但是根据建模实体的理论,这个解决方案不是很纯粹。在这种情况下使用虚拟方法将比正确实现更具窍门性 例如,IR通道具有不同的脉冲持续时间和封装结构的时序。使用一组特定的常量值定义一组子类(不同的IR通道实现)很方便。这些值是静态的,因为它们对于class和const的每个对象都是通用的,因为它们仅在编译时需要。而且由于基类和子类的内部实现略有不同,它们之间的最佳关系是super class - child class 我的原始问题现在是理由吗?

6 个答案:

答案 0 :(得分:7)

您将需要一个模板,并更改继承以使用模板,如您所见。诀窍是让它工作是否派生类有一个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
}

答案 1 :(得分:4)

根据定义,你用静态成员做的任何事情都会“黯然失色”,而不是“覆盖”。你可以在“B”中重新实现“printX()”,但你不会真的重写这种行为;因为这会使用黯然失色,行为将完全取决于编译时,而不是运行时类型。

答案 2 :(得分:2)

只需将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();
    }

答案 3 :(得分:0)

简短回答:你不能。

稍长,更复杂的答案:嗯,也许你可以。使用模板

#include <iostream>

template <typename T> struct A 
{
    static const int X = 1;

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

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

int main(int, char **)
{
    B b;

    b.printX();

    return 0;
}

答案 4 :(得分:0)

好的,我会一起玩......你想要将它嵌套在一个以上的深度。细

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

您甚至可以跳过每个班级中的static const int X = ...;,并根据需要执行public T<1>public T<2>等。

答案 5 :(得分:0)

我不会使用angular.jsonstatic,而是使用常规常量属性和构造函数。

例如:

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

-优化这些常量现在是编译器的工作。而且,如果您不打算使用成千上万个对象X = 5, FN = data.dat ,则不必担心使这些常量成为B