2012-10-18 182 views
0

基類成員函數可以直接訪問子類成員函數嗎?基類成員函數直接訪問子類成員函數?

我找到的代碼從Androind,所述BufferQueue繼承BnSurfaceTexture,並且具有一個成員函數 「requestBuffer」。

在基類BnSurfaceTexture,我發現它只是直接調用requestBuffer。

基類BnSurfaceTexture如何知道函數「requestBuffer」?

感謝


基類成員函數:

status_t BnSurfaceTexture::onTransact(
    uint32_t code, const Parcel& data, Parcel* reply, uint32_t flags) 
{ 
    switch(code) { 
     case REQUEST_BUFFER: { 
      CHECK_INTERFACE(ISurfaceTexture, data, reply); 
      int bufferIdx = data.readInt32(); 
      sp<GraphicBuffer> buffer; 
      /* it call requestBuffer directly */ <-------- 
      int result = requestBuffer(bufferIdx, &buffer); 
      reply->writeInt32(buffer != 0); 


子類聲明&實現:

class BufferQueue : public BnSurfaceTexture { 

private: 
    virtual status_t requestBuffer(int slot, sp<GraphicBuffer>* buf); 


status_t BufferQueue::requestBuffer(int slot, sp<GraphicBuffer>* buf) { 
    ATRACE_CALL(); 
    ST_LOGV("requestBuffer: slot=%d", slot); 
    Mutex::Autolock lock(mMutex); 
    ... 
    return NO_ERROR; 
} 

回答

2

基類BnSurfaceTexture如何知道函數「requestBuffer」?

此功能必須一直至少聲明基類(也有可能是一些默認實現定義),它必須是virtual

所以,在編譯時,編譯器會發現這樣的函數存在。
函數調用在運行時解析。這是多態性。


微小例如:

class Base 
{ 
public: 
    virtual void f() { /* Base */ } // could be pure virtual 
    virtual void g() { f(); }; 
}; 

class Derived: public Base 
{ 
public: 
    virtual void f() { /* derived */ } 
}; 

當你有

Base* pB = new Derived; 
pB->g(); 

g()將調用Derived::f;

+1

謝謝Kiril〜這正是我想知道的! –

2

只要確保基類的功能是聲明和派生類是之前的基類功能定義定義定義。下面是一個例子

#include <iostream> 

class Base 
{ 
    public : 

    void call_derived(); 
}; 

class Derived : public Base 
{ 
    public : 

    void derived_fun() 
    { 
     std::cout << "Derived class member function called!" << std::endl; 
    } 
}; 

void Base::call_derived() 
{ 
    static_cast<Derived *>(this)->derived_fun(); 
} 

int main() 
{ 
    Derived dobj; 
    dobj.call_derived(); 

    return 0; 
} 

不過,這款採用static_cast是不安全的,如果你嘗試call_derived一個不完整的對象編譯器不會抱怨。但是,至少在調試模式下,您可以添加斷言assert(dynamic_cast<Derived *>(this)以進行調試。或者,您可以聲明基類的構造函數,析構函數protected,以防止創建不完整的對象,或嘗試銷燬派生對象,同時基不是多態的。還存在其他更先進的技術,如CRTP,它們也使用static_cast並提供不具有virtual功能的靜態多態性。

這個答案可能不完全是你想要的。它只表明可以在基類中調用派生類成員,即使它沒有在基類中定義。但要直接調用它,不需要任何投射,您仍然需要virtual函數。

+0

謝謝Yan〜雖然這不是我想要的完全答案。但它仍然是一個很好的伎倆。 –