2013-01-12 54 views
0

我有一個設計爲通用的,用於任何一類,這看起來有點像這樣:覆蓋基類調用的函數?

class FixedByteStream { 
public: 
    FixedByteStream(const char* source) 
    { 
    size = strlen(source); 
    copy(source); 
    } 

    /* Many more constructors here */ 

protected: 
    void copy(const char* source) 
    { 
    address = allocate(); 
    //... 
    } 

    /* Plus other functions that call allocate() */ 

    char* FixedByteStream::allocate() 
    { 
    return (char*)malloc(size); 
    } 
} 

,我已擴大了這一類,因此,它可以使用特定項目的內存池。

class PooledByteStream : public FixedByteStream { 
public: 
    PooledByteStream::PooledByteStream() : FixedByteStream() {} 

protected: 
    char* PooledByteStream::allocate() 
    { 
    return (char*)PooledByteStream::pool.allocate(size); 
    } 
} 

PooledByteStream應該是相同到FixedByteStream,與所有的相同的功能和構造,不同之處在於被稱爲分配時(),它應該從存儲器池中檢索指針。

但是,PooledByteStream :: allocate()不是有史以來調用。不是來自繼承的構造函數,也不是來自其他繼承的函數(即調用繼承的copy())。從基類繼承的任何東西都完全沒有意識到allocate()應該現在做一些完全不同的事情。

問題是,我該如何解決這個問題?我如何讓繼承的函數調用覆蓋函數,而不是基類的函數?從基類複製粘貼所有必要的函數會抹殺繼承點,所以我假設這不是答案。

注意:我不尋找內存管理或其他方式來達到相同的最終結果的建議。這只是一個例子!

+1

你讓虛擬? – chris

+0

你可以發佈FixedByteStream的默認構造函數嗎? – billz

回答

5

您需要聲明allocate()爲虛擬以覆蓋它。但是,基類構造函數不能調用派生類的覆蓋,因爲派生類尚未構造,並且基類析構函數不能調用派生類的覆蓋,因爲派生類已被破壞。

如果必須調用基類的構造函數allocate(),您可以使用模板來避開限制,如:

template<typename Derived> 
class FixedByteStreamBase 
{ 
public: 
    FixedByteStreamBase(const char* source) 
    { 
    size = strlen(source); 
    copy(source); 
    } 

    /* Many more constructors here */ 

protected: 
    void copy(const char* source) 
    { 
    address = Derived::allocate(); 
    //... 
    } 

    /* Plus other functions that call allocate() */ 
}; 

class FixedByteStream : public FixedByteStreamBase<FixedByteStream> 
{ 
public: 
    static char* allocate() 
    { 
     return (char*)malloc(size); 
    } 
}; 

class PooledByteStream : public FixedByteStreamBase<PooledByteStream> 
{ 
public: 
    static char* allocate() 
    { 
     return (char*)pool.malloc(size); 
    } 
}; 

或者:

struct MallocAllocator 
{ 
    static char* allocate() 
    { 
     return (char*)malloc(size); 
    } 
}; 

struct PoolAllocator 
{ 
    static char* allocate() 
    { 
     return (char*)pool.allocate(size); 
    } 
}; 

template<typename Allocator> 
class FixedByteStreamBase { 
public: 
    FixedByteStreamBase(const char* source) 
    { 
    size = strlen(source); 
    copy(source); 
    } 

    /* Many more constructors here */ 

protected: 
    void copy(const char* source) 
    { 
    address = Allocator::allocate(); 
    //... 
    } 

    /* Plus other functions that call allocate() */ 
}; 

typedef FixedByteStreamBase<MallocAllocator> FixedByteStream; 
typedef FixedByteStreamBase<PoolAllocator> PooledByteStream; 
+0

奇怪的是,將'allocate()'聲明爲虛函數使其工作,並且調試(只是內存分析)顯示了從基礎構造函數調用的派生版本。 base * de * structor仍然調用deallocate()的基本版本(正如它所說的那樣),但它只是需要一個小的解決方法來防止它釋放混合的內存。 – DigitalMan

+0

基本類的構造函數/析構函數可以在派生類中調用overidden方法,但缺少一個編譯器錯誤是沒有可能的。當基類構造/析構函數正在運行時,派生類的vtable根本不存在於this指針中。 –

+0

我的意思是說:「在基類構造/析構函數正在運行時,派生類的vtable無法從'this'指針訪問。」 –