2013-01-12 66 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'指针访问。” –