2009-06-05 34 views
3

我有這樣的事情:強制兒童類的靜態方法重載在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>()時可能會引發編譯時錯誤?

還是不好OO設計,我應該做一些完全不同的事情?

編輯:

什麼我基本上是試圖做的,就是讓這樣的工作:

Manager manager; 

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

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

,或者更一般地說,外部抽象工廠不知道它正在生成的對象的類型,以便可以添加新的類型而無需編寫更多的代碼。

+0

你能提供關於上下文的細節嗎?看起來像你的編程某種工廠thingy。 – diapir 2009-06-05 20:13:37

+1

如果您的Manager's Produce方法無論如何都返回一個指向基類的指針,那麼使用模板有什麼意義?你可以像這樣定義你的RegisterProducer方法:void RegisterProducer(Object *(* pfnProduce)(),const char * pName) – 2009-06-05 20:46:25

回答

6

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

(1)將Produce()作爲基類的接口。

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! 
} 
1

C++不支持虛擬靜態功能。想想虛擬桌面必須要支持的東西,並且你會意識到它是一個不可行的選擇。

2

無法在子類中重寫靜態方法,只能隱藏它。也沒有任何東西類似於強制子類提供定義的抽象方法。如果你真的需要在不同的子類中有不同的行爲,那麼你應該讓Lolz()成爲一個實例方法,並像平常一樣覆蓋它。

我懷疑你在這裏接近設計問題。替代原則是面向對象設計的原則之一。它基本上說,如果B是A的一個子類,那麼只要你可以使用A就可以使用B。

0

據我瞭解你的問題,你想從父類中禁用靜態方法。你可以做這樣的事情在派生類:


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

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