Pergunta

Por que, por exemplo, que não há suporte ao idioma para examinar uma vtable? Por que eu não posso substituir a função de membro com um novo? Eu tenho um pressentimento de que existem maneiras de colocar esses recursos para uma boa utilização.

Existem outras línguas lá fora, que me permitem fazer tais coisas?

Foi útil?

Solução

A principal razão é que manter vtable como um detalhe de implementação permite que qualquer aplicação concreta para otimizá-lo como lhe aprouver; Isto significa que ele pode, por exemplo aparar ou mesmo eliminar vtable completamente se pode provar que não há chamadas virtuais para um determinado método (ou todos os métodos). Ou pode substituir uma expedição vtable com um if-else tipo de seleção se por exemplo ele vê que há apenas algumas alternativas (isso pode ser vantajoso porque previsão de desvios funcionará neste caso, mas não com vtables, e também porque if-else ramos podem então ser embutido). Pode reordenar métodos vtable de tal forma que a maioria dos comumente chamados os vir mais cedo, ou de tal forma que aqueles que são comumente chamados um após outro preenchimento ranhuras adjacentes em vtable para tirar vantagem de caching. E assim por diante. Claro, todas essas implementações também faria disposição vtable totalmente imprevisível, e, portanto, inútil, se fosse para ser exposto (pela especificação de idioma) para a implementação.

Assim, vtables não são tão simples quanto parecem ser. Por exemplo, compiladores muitas vezes têm de gerar thunks para ponteiro fix-up this para coisas tais herança virtual, ou herança múltipla combinado com tipos de retorno covariantes. Esta é novamente algo que não tem um "melhor caminho único" para fazê-lo (que é por diferentes compiladores fazê-lo de forma diferente), e padronizando-lo de forma eficaz exigiria de se estabelecer em uma maneira particular.

Dito isso, "comutação vtable" é uma técnica potencialmente útil se exposto como uma construção de nível superior (para que otimizações ainda são possíveis). Para um exemplo, ver UnrealScript, que permite a definição de várias href="http://wiki.beyondunreal.com/State" para uma classe (um padrão, outra nomeado), e substituir alguns métodos em estados nomeados. As classes derivadas podem substituir métodos mais em estados existentes, ou adicionar seus próprios estados e override neles. Além disso, os Estados podem estender outros estados (por isso, se um método não é substituído por um estado particular, ele volta para o estado de "pai", e assim por diante até que a corrente atinge o estado padrão). Para a modelagem ator (que jogos são essencialmente) tudo isso faz muito sentido, razão pela qual UnrealScript tem. E o mecanismo de implementação eficiente óbvia para tudo isso é comutação vtable, com cada estado tendo uma vtable separado.

Outras dicas

Porque é um detalhe de implementação do compilador. Que a implementação pode mudar, e qualquer código que depende de que seria frágil na melhor das hipóteses.

C ++ é uma linguagem onde você nunca 'paga' o que você não usa. Este tipo de suporte de tempo de execução seria contrário a essa filosofia.

Há uma abundância de línguas (na extremidade mais dinâmica do espectro) que suporte isso.

Porque ele não tem que ser implementado como um VTable, embora este é geralmente o caso. Em suma, não existe tal coisa como VTable em C ++!

JavaScript, Python e Ruby podem fazer isso. Nessas línguas, de classe e instância definições são mutáveis ??em tempo de execução. Abstratamente, cada objeto e tipo é um dicionário de variáveis ??de membro e métodos que podem ser examinados e atualizados.

Isto não é possível em C ++ porque exigiria ser capaz de reescrever o código binário gerado, que pode transportar um custo de desempenho substancial.

vtables só existem em certas circunstâncias, em alguns compiladores (ou seja, eles não são especificados no padrão, mas um detalhe de implementação). Mesmo quando eles existem, eles só ocorrem quando você tem funções virtuais e precisam do engano para implementar polimorfismo. Quando isso não é necessário que eles podem ser otimizados para fora, salvando a sobrecarga do engano na chamada.

Infelizmente (ou não, dependendo de suas opiniões sobre o assunto ;-), C ++ não foi projetada para patching apoio macaco. Em alguns casos (por exemplo, COM) o vtable é uma parte da implementação e você pode ser capaz de picar sobre os bastidores. No entanto, isso nunca seria apoiado ou portátil.

Eu acredito que você pode fazer coisas como que em linguagens dinâmicas como Python:

>>> class X():
...     def bar(self): print "bar"
...     
>>> x = X()
>>> x.bar()
bar
>>> def foo(x): print "foo"
... 
>>> X.bar = foo
>>> x.bar()
foo

A diferença com uma linguagem estática como C ++ é que os olhares intérprete segurança de todos os nomes em tempo de execução e, em seguida, decide o que fazer.

Em C ++ é provável outras soluções para o "substituir uma função membro com outro" problema, o mais simples dos quais pode estar usando ponteiros de função:

#include <iostream>

class X;
typedef void (*foo_func)(const X&);

void foo(const X&) { std::cout << "foo\n"; }
void bar(const X&) { std::cout << "bar\n"; }

class X
{
    foo_func f;
public:
    X(): f(foo) {}
    void foobar() { f(*this); }
    void switch_function(foo_func new_foo) { f = new_foo; }
};

int main()
{
    X x;
    x.foobar();
    x.switch_function(bar);
    x.foobar();
}

(foo e bar não use o X & argumento, neste exemplo, semelhante ao exemplo Python)

Eu estou trabalhando em uma linguagem estaticamente compilado que expõe o vtable, e acreditem que é um pouco de cabelo para expor.

  • Qualquer coisa que você pode fazer em C ++, você pode fazer em linha reta C com um pouco de graxa cotovelo.
  • Qualquer programa modesta e razoável C deve compilar em C ++.

Talvez o que você quer é implementar seus próprios vtables sem o uso de C ++ 's built-in facilidade. Você vai ter um monte de diversão com ponteiro-para-membro-funções (de PTMF)!

Você vai ter dificuldade em encontrar uma linguagem compilada com introspecção vtable porque há pouca demanda e não é fácil de implementar. Para linguagens interpretadas, porém, a situação é o contrário.

Existem outras línguas fora lá que me permite fazer tais coisas?

Objectivo-C (e Objective-C ++ bem) permite a substituição de tempo de execução de métodos já compilado. É tanto a melhor combinação de estática e técnicas dinâmicas ou o pior, dependendo de quem você perguntar.

Como os outros têm para fora pontas, não existe o conceito de padrão "vtable" no C ++, como é apenas uma técnica de aplicação quase universal, bem como desconfiguração do nome.

Se você está procurando por ser capaz de redefinir funções na mosca em uma linguagem compilada, você pode estar interessado em Common Lisp. Não tem que ser outros, mas o único outras línguas que posso pensar quer ter herança e funções estáticas ou são interpretados em um grande custo no desempenho.

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