Pergunta

Eu quero chamar a implementação de classe base de uma função virtual usando um ponteiro de função de membro.

class Base {
public:
    virtual void func() { cout << "base" << endl; }
};

class Derived: public Base {
public:
    void func() { cout << "derived" << endl; }

    void callFunc()
    {
        void (Base::*fp)() = &Base::func;
        (this->*fp)(); // Derived::func will be called.
                       // In my application I store the pointer for later use,  
                       // so I can't simply do Base::func().
    }
};

No código acima a implementação da classe derivada de func será chamado de callfunc. Existe uma maneira eu posso salvar uma função ponteiro membro que aponta para a Base :: func, ou terei de usar using de alguma forma?

Na minha impulso aplicativo eu uso real :: bind para criar um objeto boost :: função em callfunc que eu mais tarde usar para func chamada de outra parte do meu programa. Então, se boost :: bind ou boost :: função de ter alguma forma de contornar este problema que também ajuda.

Foi útil?

Solução

Quando você chamar um método virtual através de uma referência ou um ponteiro que você vai sempre ativar o mecanismo de chamada virtual que encontra o tipo mais derivado.

Sua melhor aposta é a de adicionar uma função alternativa que não é virtual.

Outras dicas

O que você está tentando fazer, infelizmente não é possível. Ponteiro-para-membro-funções são concebido para manter a virtualness da função apontou-a.

Seu problema é que um ponteiro de função de membro não é exatamente o mesmo que um ponteiro de função nua. Na verdade, não é apenas um ponteiro, mas um consideravelmente mais complexa estrutura , que varia em seus detalhes ao nível da implementação do compilador. Quando você chamá-lo através do (this->*fp)() sintaxe na verdade você está chamando-o sobre o objeto original, que faz com que a função expedição virtual.

Uma coisa que o trabalho poder é lançá-lo a um não-método tipo de ponteiro. Este é um pouco chia mas eu pensar ele deve funcionar. Você ainda precisa passar por um Base * mas você fazê-lo de forma explícita e o envio de função virtual é contornado:

typedef void BasePointer(Base*);

void callFunc()
{
    BasePointer fp = (BasePointer *)&Base::func;
    fp(this);
}

Update: Ok, não, você não pode fazê-lo dessa maneira. É ilegal, e não seria seguro se era legal. A C ++ FAQ tem mais sobre este . Mas sabendo que não resolver o seu problema. A questão é que, ponteiro-a-objeto ou ponteiro-para-membro, se você quiser chamar Base::func através de um ponteiro Base, o objeto que está a apontar must também ser um Base. Se você pode organizar isso, então você pode usar um ponteiro de função de membro.

Aqui está outro pensamento, não é bonito, mas pelo menos viável. Fornecer uma função em Derived, não-virtual, que explicitamente chama Base::func. Aponte para que, em vez. Não será ampliado se você precisar fazer isso no caso geral de lotes de diferentes variantes do func e callFunc mas ele vai funcionar bem para um método.

Existe alguma razão específica para fazer isso através de um ponteiro de função?

Você deve ser capaz de escrever apenas:

Base::func();

para chamar a implementação da classe base.

Além do que quark diz, uma observação mais geral é que você deve usar uma implementação de sinal / slot em vez de um ponteiro de função nua. Impulso tem um, há libsigc e um monte de outros.

O que há de errado com isso?

(Base(*this).*fp)();

Agora, se você está satisfeito com isso, ele levanta a questão de por que você está mesmo usando um ponteiro de função em primeiro lugar. Acho que alguns mais contexto pode ajudar.

Licenciado em: CC-BY-SA com atribuição
Não afiliado a StackOverflow
scroll top