たとえば、vtableを調べるための言語サポートがないのはなぜですか?メンバー関数を新しいものに置き換えられないのはなぜですか?そのような機能を有効に活用する方法があると直感しています。
私がそのようなことをすることを可能にする他の言語はありますか?
たとえば、vtableを調べるための言語サポートがないのはなぜですか?メンバー関数を新しいものに置き換えられないのはなぜですか?そのような機能を有効に活用する方法があると直感しています。
私がそのようなことをすることを可能にする他の言語はありますか?
コンパイラの実装の詳細だからです。その実装は変更される可能性があり、それに依存するコードはせいぜい壊れやすいでしょう。
C ++は、使用しないものに対して「お金を払う」ことのない言語です。この種のランタイムサポートは、その哲学に反して実行されます。
それをサポートする言語はたくさんあります(スペクトルのより動的な端にあります)。
VTable
通常はそうですが、として実装する必要はないためです。VTable
つまり、 C++のようなものはありません。
主な理由は、vtableを実装の詳細として保持することで、具体的な実装が適切と思われる場合に最適化できることです。これは、特定のメソッド(またはすべてのメソッド)に仮想呼び出しがないことを証明できる場合、たとえばvtableを完全に削除または削除できることを意味します。または、たとえば、選択肢が少ないことがわかった場合は、vtableディスパッチをif-elseタイプのチェックに置き換えることができます(この場合、分岐予測は機能しますが、vtablesでは機能しないため、またif-elseであるため、これは有利です。その後、ブランチをインライン化できます)。最も一般的に呼び出されるメソッドが早く来るように、または一般的に次々に呼び出されるメソッドがキャッシュを利用するためにvtableの隣接するスロットを埋めるように、vtableのメソッドを並べ替えることができます。などなど。もちろん、
同様に、vtablesは思ったほど単純ではありません。たとえば、コンパイラは、this
仮想継承や、共変の戻り型と組み合わせた多重継承などのポインタを修正するために、サンクを生成する必要があることがよくあります。これもまた、それを行うための「単一の最良の方法」がないものであり(これが、異なるコンパイラーが異なる方法で行う理由です)、それを標準化するには、特定の方法で効果的に解決する必要があります。
とは言うものの、「vtableスイッチング」は、より高いレベルの構成として公開されている場合(最適化が引き続き可能であるため)、潜在的に有用な手法です。例については、UnrealScriptを参照してください。これにより、複数の状態を定義できます。クラス(1つはデフォルト、もう1つは名前付き)の場合、名前付き状態の一部のメソッドをオーバーライドします。派生クラスは、既存の状態でより多くのメソッドをオーバーライドすることも、独自の状態を追加してオーバーライドすることもできます。さらに、状態は他の状態を拡張できます(したがって、メソッドが特定の状態でオーバーライドされない場合、チェーンがデフォルト状態に達するまで「親」状態にフォールバックします)。アクターモデリング(基本的にゲーム)の場合、これはすべて非常に理にかなっています。そのため、UnrealScriptにそれがあります。そして、これらすべての明らかで効率的な実装メカニズムはvtableスイッチングであり、各状態には個別のvtableがあります。
JavaScript、Python、Rubyはすべてこれを行うことができます。これらの言語では、クラスとインスタンスの定義は実行時に変更可能です。要約すると、各オブジェクトとタイプは、検査および更新できるメンバー変数とメソッドのディクショナリです。
これはC++では不可能です。生成されたバイナリコードを書き直す必要があり、かなりのパフォーマンスコストがかかる可能性があるためです。
Vtableは、一部のコンパイラの特定の状況でのみ存在します(つまり、Vtableは標準では指定されていませんが、実装の詳細で指定されています)。それらが存在する場合でも、仮想関数があり、ポリモーフィズムを実装するために間接参照が必要な場合にのみ発生します。これが不要な場合は、最適化して、コールの間接参照のオーバーヘッドを節約できます。
悲しいことに(または、問題に関するあなたの見解によっては;-)、C++はモンキーパッチをサポートするように設計されていませんでした。場合によっては(COMなど)、vtableは実装の一部であり、舞台裏で話をすることができる場合があります。ただし、これはサポートされたり、移植可能になることはありません。
Pythonのような動的言語でそのようなことができると思います。
>>> class X():
... def bar(self): print "bar"
...
>>> x = X()
>>> x.bar()
bar
>>> def foo(x): print "foo"
...
>>> X.bar = foo
>>> x.bar()
foo
C ++のような静的言語との違いは、インタプリタが実行時にすべての名前を検索してから、何をするかを決定することです。
C ++では、「メンバー関数を別の関数に置き換える」問題に対する他の解決策がある可能性があります。最も単純な解決策は、関数ポインターを使用することです。
#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();
}
(この例では、Pythonの例と同様に、fooとbarはX&引数を使用しません)
私はvtableを公開する静的にコンパイルされた言語に取り組んでおり、公開するのはかなりの髪の毛だと信じています。
たぶんあなたが望むのは、C++の組み込み機能を使用せずに独自のvtablesを実装することです。メンバー関数へのポインター(ptmf)を楽しむことができます!
需要がほとんどなく、実装が容易ではないため、vtableイントロスペクションを使用してコンパイルされた言語を見つけるのは困難です。ただし、インタプリタ言語の場合、状況は逆です。
私がそのようなことをすることを可能にする他の言語はありますか?
Objective-C(およびObjective-C ++も)を使用すると、コンパイル済みのメソッドを実行時に置き換えることができます。誰に尋ねるかによって、静的手法と動的手法の最良の組み合わせか、最悪の組み合わせのいずれかになります。
他の人が指摘しているように、C ++標準には「vtable」の概念はありません。これは、名前マングリングのように、ほぼ普遍的な実装手法であるためです。
コンパイルされた言語でその場で関数を再定義できることを探しているなら、CommonLispに興味があるかもしれません。他にもあるはずですが、私が考えることができる他の言語は、静的な継承と関数を持っているか、パフォーマンスに大きなコストをかけて解釈される唯一の言語です。