C++静态常量成员重写

yh2wf1be  于 2023-04-08  发布在  其他
关注(0)|答案(7)|浏览(118)

请考虑以下情况。

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?
常量和方法都必须是静态的,因此虚方法是不合适的.
对于那些认为他们比我更了解我的任务,并希望看到我重新思考它的人,我会解释我努力的目标:)
想象一个类,它的行为基于一组静态常量。实现具有不同常量集的子类,从而具有不同行为的最简单方法是从具有特定常量值集的前一个类派生类。可以使用虚函数来解决该任务。当然可能,毫无疑问。但是这个解决方案在符合模型化实体理论的意义上并不是很纯粹。在这种情况下使用虚方法与其说是正确的实现,不如说是一种技巧。
比如说红外通 prop 有不同的脉冲持续时间和封装结构,便于定义子类集这些值是静态的,因为它们对于class和const的每个对象都是通用的,因为它们只在编译时需要。由于基类和子类的内部实现略有不同,它们之间的最佳关系是super class - child class
这是否我原来的质询的理据呢?

stszievb

stszievb1#

你将需要一个模板,并改变继承以使用模板,正如你将看到的。诀窍是使它工作,无论派生类是否有一个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
}
cwxwcias

cwxwcias2#

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

gab6jxml3#

根据定义,你对静态成员所做的任何事情都是“覆盖”,而不是“重写”。因为这将使用遮蔽,所以行为将完全取决于编译时类型,而不是运行时类型。

vwkv1x7d

vwkv1x7d4#

我不使用statictemplate,而只使用常规的常量属性和构造函数。
例如:

#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,那么把这些常量设为static就不值得你操心了。
1tu0hz3e

1tu0hz3e5#

简短回答:你不能。
稍微长一点,更复杂的答案:好吧,也许你可以。用模板!

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

8fsztsew6#

好吧,我会沿着的……你想把这个嵌套得比一层深。好吧。

#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>等。

xoshrz7s

xoshrz7s7#

为什么不使用模板?

constexpr int nfo[]{ 0, 1, 2, 3 };

template <int N>
class Haha {
public:
        const static int BOOM = nfo[ N ];
};
int main() {
        std::cout << Haha<2>::BOOM << std::endl; // 2
}

相关问题