7

Java のようなオブジェクト指向プログラミング言語では、クラス Object がクラス階層の最上位にあることを理解しています。また、.NET に参照型と値型があることも理解しています。また、C ベースの言語での型定義も理解しています。

これにもかかわらず; オブジェクトがVB6( http://msdn.microsoft.com/en-us/library/aa338034%28v=vs.60%29.aspx )にあるものと、正確にバリアントとは何かを理解するのに苦労しています。バリアントとは何ですか?オブジェクトはVB6でどのように実装されていますか?

4

2 に答える 2

10

VB6 で使用されるすべてのオブジェクトは COM オブジェクトです。COM オブジェクトは基本的に可変長データ構造であり、その可変長ヘッダーには VTable への任意の数の 32 ビット ポインターが含まれ、連続するバイトにはオブジェクトのインスタンス データが含まれます。例えば、

Bytes
0-3    VTable1 pointer
4-7    VTable2 pointer
8-11   VTable3 pointer
...
       Instance data

VTable は、関数への 32 ビット ポインターの配列であり、すべて「this」インスタンス ポインターが渡されます。

Bytes
0-3    Func1(this, ..., ...)
4-7    Func2(this, ..., ...)
8-11   Func3(this, ..., ...)
...

その他の唯一の仕様は、すべての VTableが IUnknown から継承する必要があることです。つまり、最初の 3 つの関数は次のようにする必要があります。

QueryInterface()
AddRef()
Release()

基本的に、QueryInterface() を使用すると、COM オブジェクトが特定のインターフェイス (UUID で表される) をサポートしているかどうかを確認できます。AddRef() を使用すると、オブジェクト ライターは内部参照カウントをインクリメントできます。Release() を使用すると、オブジェクト ライターは参照カウンターをデクリメントし、カウントがゼロになるとオブジェクトを破棄できます。VB でこれらのメソッドを呼び出すことはありません。コンパイラがこれらの呼び出しを追加します (VB6 の利点の 1 つ)。

詳細については、 http://msdn.microsoft.com/en-us/library/windows/desktop/ms680509 (v=vs.85).aspx を参照してください。

VB の「オブジェクト」タイプは、IDispatch インターフェイスをサポートするオブジェクトへの参照です ( http://msdn.microsoft.com/en-us/library/windows/desktop/dd318520(v=vs.85).aspxを参照) 。 . これにより、VB および VBScript でレイト バインディングが可能になります。VB6 で記述されたすべてのオブジェクトは、IDispatch から継承するインターフェイスを自動的に実装します。これは、アーリー バインディングとレイト バインディングをサポートするため、デュアル インターフェイスと呼ばれます。

COM には直接型システムが組み込まれていないことに注意してください。ただし、ITypeInfo インターフェイスをサポートすることを選択できます。これにより、オブジェクトについて追加したい情報にオブジェクトのユーザーがアクセスできるようになります (タイプ ライブラリを使用してこの情報を格納する既定の実装を使用する方が簡単です)。

Bob Riemersma が言及したように、Variant 型は実際には 16 バイトの構造であり、カプセル化されているオートメーションの型を示す 2 バイトの整数 (vt) を持ち、最後の 8 バイトを使用して最大 8 個の値の型を含めることができます。バイト、または別の型への 32 ビット ポインター。VB は、その内部関数を使用して、VB 型とバリアントの間で必要なすべての変換、および必要なすべてのメモリ割り当てと割り当て解除を行います。オブジェクトへのポインターをバリアントにコピーし、オブジェクトの AddRef() メソッドを呼び出すことにより、バリアントに COM オブジェクトへの参照を含めることができます。

于 2012-04-11T14:30:59.483 に答える
5

これを別の問題に分けてみましょう。

まず、VB6 は VB.Net ではなく、.Net Framework を使用せず、代わりに古い COM フレームワークを使用します。(これをすでに知っているかどうかはわかりません)。

第二に、リンクが指しているのは、実際にはVB6 に組み込まれているクラスです。とはいえ、はい、それらを「オブジェクト」と呼んでいます。彼らのずさんな用語。

第 3 に、おそらく最も重要なことですが、VB6 ではすべてがオブジェクトではなく、オブジェクトはデータ型のデフォルトまたは支配的なカテゴリでさえありません。つまり、.Net の値の型のようなものですが、はるかに少ないものです (ほとんどの場合、実行時の型コンテナーさえなく、メモリ内のアドレスだけです)。

そのため、ほとんどのデータ項目はオブジェクトではなく、したがってクラスを持たず、いかなる種類の継承も持たず、他のものから派生せず、「型階層」を持たず、"型階層の最上位 (ただし、クラス/オブジェクトであったものにはこれらすべてが含まれていました)。そのため、他のデータ型に使用できるベース/ルート データ型がありませんでした。これは、あらゆる種類のパラメーター受け渡しなどの状況で問題となっていました。

バリアントは、この問題に対処するために以前のバージョンの VB で (VB のオブジェクトよりも前に) 実装された、この問題に対する一種の以前の解決策でした。Variant は、任意のデータ型の別の項目をラップする単なる動的記述子です。それを使用すると、(通常) 含まれているものを直接使用しているように動作しますが、実際には Variant を通過して、現在含まれているデータ項目のタイプに到達します。

Variant 自体は、そのコンテンツのデータ型が何であるかを追跡し、それにアクセスする VB コードが異なる/適切に動作するようにします (プリミティブな種類のポリモーフィズム)。

これが厄介でオーバーヘッドが多かったように聞こえる場合は、そうでした。しかし、当時は「任意のデータ型」を処理する必要がある場合に利用できる最良のソリューションでした。

于 2012-04-10T20:39:27.127 に答える