Возможно ли, чтобы функция-член базового класса могла напрямую обращаться к функции-члену дочернего класса?
Я нашел код от 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;
}
Как базовый класс 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
;
Просто убедитесь, что функция базового класса объявленный, и производный класс определить до определение функции базового класса определение. Вот пример
#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
функции.