2014-01-28 74 views
1

我有一堆以不同方式實現相同靜態內聯方法的類(我從未實例化過)。我想了解這些課程是否可以有共同的家長。 目的不在於虛擬調用,而是爲了強制任何想要以不同方式再次實現該方法的新類的結構。我可以這樣做嗎?我開始認爲這不是C++提供的一種功能。具有靜態(內聯)方法的從未實例化的類的基類

class XXX { 
public: 
    ///Should force any derived class to implement 
    ///bool compute(const unsigned char i1, const unsigned char i2); 
}; 

class GreaterThan : public XXX { 
public: 
    static inline bool compute(const unsigned char i1, const unsigned char i2) { 
     return i1 > i2; 
    } 
}; 

class NotGreaterThan : public XXX { 
public: 
    static inline bool compute(const unsigned char i1, const unsigned char i2) { 
     return i1 <= i2; 
    } 
}; 

class NotLessThan : public XXX { ///This should not compile 
public: 
    static inline bool compute2(const unsigned char i1, const unsigned char i2) { 
     return i1 >= i2; 
    } 
}; 

[...] 

在基類定義的純虛方法compute不允許我定義在派生類的靜態方法。當方法不是靜態的時候會迫使我實例化類,當我將它用作函數時,並且基本上會防止內聯。

注意:有人問過類似的問題here

編輯:可能,也這不應該編譯:

class LessThan : public XXX { ///Also this should not compile 
public: 
    static inline bool compute(const float i1, const float i2) { 
     return i1 < i2; 
    } 
}; 

回答

1

這幾乎應該做你想要什麼:

#include <iostream> 

template <typename Algorithm> 
class UnsignedCharFunction { 
    public: 
    typedef Algorithm algorithm_type; 
    static bool compute(const unsigned char i1, const unsigned char i2) { 
     return call(algorithm_type::do_compute, i1, i2); 
    } 

    private: 
    static bool call(
     bool (*f)(const unsigned char, const unsigned char), 
     const unsigned char i1, const unsigned char i2) { 
     return f(i1, i2); 
    } 
}; 

class GreaterThan : public UnsignedCharFunction<GreaterThan> { 
    friend class UnsignedCharFunction<GreaterThan>; 

    private: 
    static bool do_compute(const unsigned char i1, const unsigned char i2) { 
     return i1 > i2; 
    } 
}; 


class Invalid : public UnsignedCharFunction<Invalid> { 
    friend class UnsignedCharFunction<Invalid>; 

    private: 
    #define N 2 
    #if N == 1 
    // Fails 
    static bool no_do_compute(const unsigned char i1, const unsigned char i2) { 
     return i1 >= i2; 
    } 
    #elif N == 2 
    // Fails 
    static bool do_compute(char i1, char i2) { 
     return i1 >= i2; 
    } 
    #endif 
}; 


int main() { 
    std::cout << "A > B:" << GreaterThan::compute('A', 'B') << '\n' 
       << "B > A:" << GreaterThan::compute('B', 'A') << '\n'; 
    // If you comment next line, there will be no error. 
    Invalid::compute('A', 'B'); 
} 

差不多,模板實例化導致 - 一個編譯器錯誤將只顯示,使用該功能時。

關於在線:

volatile bool value; 
int main() { 
    value = GreaterThan::compute('A', 'B'); 
} 

00000000004005a0 <main>: 
    4005a0: movb $0x0,0x200aa5(%rip)  # 60104c <value> 
    4005a7: xor %eax,%eax 
    4005a9: retq 
    4005aa: nopw 0x0(%rax,%rax,1) 

的代碼將完全在這個簡單的小程序省略。

另一個內聯:

volatile bool value; 
volatile unsigned char a; 
volatile unsigned char b; 
int main() { 
    value = GreaterThan::compute(a, b); 
} 

00000000004005a0 <main>: 
    4005a0: movzbl 0x200aa5(%rip),%edx  # 60104c <b> 
    4005a7: movzbl 0x200a9f(%rip),%eax  # 60104d <a> 
    4005ae: cmp %al,%dl 
    4005b0: setb %al 
    4005b3: mov %al,0x200a95(%rip)  # 60104e <value> 
    4005b9: xor %eax,%eax 
    4005bb: retq 
    4005bc: nopl 0x0(%rax) 

都與 「G ++ -std = C++ 11 -O3 -g」 編譯

+0

好東西!但我想知道這是否有機會進行內聯...我會說不...... – Antonio

+0

爲了測試內聯,我認爲輸入值(在本例中爲'A'和'B')在編譯時不應該知道時間。 – Antonio

+0

@Antonio它是內聯的! –

2

你想要什麼叫靜態多態性。

根本不需要繼承。在你的榜樣,這應該強制XXX的用戶實現bool compute(const unsigned char i1, const unsigned char i2);靜態方法:

template< typename C > 
class XXX { 
public: 
    static void CallCompute(const unsigned char i1, const unsigned char i2) 
    { 
     const bool result = C::compute(i1, i2); 
     // use result somehow 
    } 
}; 

順便說一句,大家注意到,他們可以實現compute()bool compute(const T1 i1, const T2 i2);,其中T1和T2可以是任何整數或浮點數類型。

+0

你有一個非常有趣的觀點:使用將定義類必須如何實現。但是正如你指出的那樣,這隻給予有限的控制,而且它似乎不是「開發人員」友好:):我們沒有提供關於如何實現比較類的明確信息。 – Antonio

+1

@Antonio嗯,他們應該閱讀關於如何使用你的課程的文檔。除此之外,如果compute()方法丟失,編譯器會拋出錯誤,這對開發人員非常友好。 –

+0

當然,這不會導致任何編譯時錯誤,除非您實際上做了一些事情來觸發'CallCompute'的實例化(比如說調用它)。 –

0

基類不知道任何有關它的派生類,所以 有沒有真正的方法可以斷言任何東西。在許多情況下,您可以通過將基類作爲模板 來解決此問題,該模板將派生類作爲參數。然而,在這裏這不會起作用 ,但是,因爲您需要一個靜態檢查,導致 編譯時錯誤立即導出,並且在那個時刻,派生類不是完整類型,並且也不能 使用它的任何功能(即使在sizeof 表達式中也沒有)。

相關問題