簡體   English   中英

C++ 靜態常量成員覆蓋

[英]C++ static const members overriding

考慮以下。

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
現在是我原來問題的理由嗎?

正如您將看到的,您將需要一個模板,並更改繼承以使用該模板。 訣竅是不管派生類是否有一個 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
}

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

根據定義,您對靜態成員所做的任何事情都將“掩蓋”,而不是“覆蓋”。 您可以在“B”中重新實現“printX()”,但您不會真正覆蓋該行為; 因為這會使用遮蔽,所以行為將完全取決於編譯時類型,而不是運行時類型。

而不是使用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可能不值得擔心。

簡短的回答:你不能。

稍微長一點,更復雜的答案:嗯,也許你可以。 模板

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

好吧,我會一起玩……你想把這個嵌套多一層深。 美好的。

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

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM