C++ permite definir o comportamento padrão de funções-membro usando a virtual
palavra-chave, mas e se eu quiser estender uma função-membro para executar funcionalidades adicionais? Por exemplo, tenho o seguinte código:
virtual void OnSize(HWND hWnd, LPARAM lParam) {
cxClient = LOWORD(lParam);
cyClient = HIWORD(lParam);
rect = { 0, 0, cxClient, cyClient };
}
cxClient
, cyClient
e rect
são variáveis de membro que são atualizadas ao receber uma WM_SIZE
mensagem. Se eu quiser atualizar a barra de rolagem em uma classe herdada, precisarei substituir a função para adicionar essa funcionalidade, mas precisarei repetir o código para atualizar as variáveis de membro:
void OnSize(HWND hWnd, LPARAM lParam) override {
cxClient = LOWORD(lParam);
cyClient = HIWORD(lParam);
rect = { 0, 0, cxClient, cyClient };
vScrollBar->setInfo(cyClient); // new functionality
}
Por que o C++ não fornece extend
palavras-chave para permitir a extensão do comportamento padrão de uma função virtual, ou seja, manter o comportamento padrão e incorporar funcionalidades adicionais. por exemplo:
void OnSize(HWND hWnd, LPARAM lParam) extend {
vScrollBar->setInfo(cyClient); // new functionality
}
Isso será considerado na próxima revisão do C++?
Em
DerivedClass::OnSize()
, você pode ligarBaseClass::OnSize()
para conseguir exatamente o que deseja. Nenhuma palavra-chave especial é necessária.O comitê C++ hesita em adicionar palavras-chave adicionais à linguagem, especialmente para coisas que sempre foram possíveis sem elas. Existe o perigo de tornar o código existente, que pode usar macros, extensões de compilador, etc., inválido por tais extensões da linguagem propriamente dita. Portanto, eu ficaria bastante surpreso em ver
extends
sendo considerado para as próximas revisões do C++. A construção existente permite que as classes derivadas tenham código antes e depois da chamada para a funcionalidade da classe base, o que é realmente superior aoextends
.Uma maneira de contornar esse problema é fornecer duas funções. Uma função concreta que não é virtual que possui o código comum para ser executada e, em seguida, outra função virtual que você chama no final da função concreta que possui o comportamento específico da classe que você deseja incorporar. Isso seria parecido
e agora, se você tiver um
Derived
objetod
chamandodo_action
, chamará a função da classe base que executará o código comum e, em seguida, despachará virtualmente parad
'sdo_action_impl
.