簡體   English   中英

在 C++ 中的子類中強制執行靜態方法重載

[英]Enforce static method overloading in child class in C++

我有這樣的事情:

class Base
{
  public:
    static int Lolz()
    {
      return 0;
    }
};

class Child : public Base
{
  public:
    int nothing;
};

template <typename T>
int Produce()
{
  return T::Lolz();
}

Produce<Base>();
Produce<Child>();

兩者都返回 0,這當然是正確的,但不需要。 無論如何要在第二個類中強制執行 Lolz() 方法的顯式聲明,或者在使用Produce<Child>()時可能會拋出編譯時錯誤?

或者是糟糕的面向對象設計,我應該做一些完全不同的事情?

編輯:

我基本上想做的是做這樣的事情:

Manager manager;

manager.RegisterProducer(&Woot::Produce, "Woot");
manager.RegisterProducer(&Goop::Produce, "Goop");

Object obj = manager.Produce("Woot");

或者,更一般地說,是一個不知道它產生的對象類型的外部抽象工廠,這樣就可以在不編寫更多代碼的情況下添加新類型。

有兩種方法可以避免它。 其實,這取決於你想說什么。

(1) 將Produce()作為Base類的接口。

template <typename T>
int Produce()
{
  return T::Lolz();
}
class Base
{
    friend int Produce<Base>();

protected:
    static int Lolz()
    {
        return 0;
    }
};

class Child : public Base
{
public:
    int nothing;
};

int main(void)
{
    Produce<Base>(); // Ok.
    Produce<Child>(); // error :'Base::Lolz' : cannot access protected member declared in class 'Base'
}

(2) 使用模板特化。

template <typename T>
int Produce()
{
  return T::Lolz();
}
class Base
{
public:
    static int Lolz()
    {
        return 0;
    }
};

class Child : public Base
{
public:
    int nothing;
};

template<>
int Produce<Child>()
{
    throw std::bad_exception("oops!");
    return 0;
}

int main(void)
{
    Produce<Base>(); // Ok.
    Produce<Child>(); // it will throw an exception!
}

沒有辦法覆蓋子類中的靜態方法,只能隱藏它。 也沒有任何類似於抽象方法的東西會強制子類提供定義。 如果您確實需要在不同的子類中使用不同的行為,那么您應該使 Lolz() 成為一個實例方法並照常覆蓋它。

我懷疑您在這里接近設計問題。 面向對象設計的原則之一是替代原則。 它基本上是說,如果 B 是 A 的子類,那么在任何可以使用 A 的地方使用 B 都必須是有效的。

或者可能在使用 Produce<Child>() 時拋出編譯時錯誤

現代解決方案是使用delete

class Child : public Base
{
  public:
    int nothing;
    static int Lolz() = delete;
};

它有助於避免大量樣板文件並清楚地表達您的意圖。

C++ 不支持虛擬靜態函數。 想想 vtable 必須是什么樣子來支持它,你會意識到它是不可能的。

據我了解您的問題,您想從父類中禁用靜態方法。 您可以在派生類中執行以下操作:


class Child : public Base
{
public:
    int nothing;
private:
    using Base::Lolz;
};

現在Child::Lolz成為私有的。 但是,當然,修復設計要好得多:)

暫無
暫無

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

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