-PR-
解決
済み

参照なバリアント

  • 暇なときにでも
  • 質問No.93172
  • 閲覧数200
  • ありがとう数8
  • 気になる数0
  • 回答数3
  • コメント数0

お礼率 77% (530/685)

VB熟達者というよりは、VBマニアな方々に質問です。

Sub Hoge(A)
A = 6
End Sub

Sub Main()
Dim N As Long
Hoge N
Debug.Print N
End Sub

このコードを実行して "6" が出力されるのは明白です。
Hogeはバリアントの参照を取るにも関わらず、LongのNを渡してそのNに6を入れてくれました。
これは、VBが引数を渡す時点で変数A用のメモリ領域をかってに確保し、Nという変数の参照型を作ったということの証拠になります。
実際、DLLでAPIを用意して、バリアント構造体のVarTypeを調べたところ、未知の16387という数値が現れました。
これは、MSDNライブラリを見たところ、VT_LONG Or VT_BYREFのようです。
このように、VBでも参照型は存在していますが、隠蔽されています。

そこで、参照型をもっと自由に使いたいと思い、参照型を作るAPIを作ってみました。
しかし、=演算子で代入しようとしたところ、参照が解除されて通常のバリアント型に戻ってしまいます。
ただし、もともとある変数の参照であるバリアント変数を別の変数の参照に変えたもののときは、参照先に代入してくれました。
どうやらVBはケチなようで、VBが内部で引数として作った参照変数以外は、参照している先に代入はしてくれないようです。

この障害を乗り越える方法を思いついた方、ぜひ教えてください。
通報する
  • 回答数3
  • 気になる
    質問をブックマークします。
    マイページでまとめて確認できます。

質問者が選んだベストアンサー

  • 回答No.2
レベル9

ベストアンサー率 28% (10/35)

通常、VBでメソッドを呼び出すときは内部では
DISPPARAMS構造体に引数をセットします。
この構造体の中では引数はVARIANTARGにセットされ、
VARIANTARGの内部で引数のポインタが保持されます。
つまり、VBでメソッドを呼び出すときは
内部的には常にVariant型で呼ばれていると考える事ができます。
Privateの関数を呼ぶときはそんな面倒くさい事をしないで
Cと同じように呼んでいるかと考えていたのですが
もし、ご質問されているような結果が出るのでしたら
DISPPARAMSを使用しているのかもしれませんね。
お礼コメント
haporun

お礼率 77% (530/685)

ということは、その構造体内で宣言された変数しか、=は参照型として扱ってくれないということなのでしょうね。

実際、Variantの参照を取る関数に、Variantの変数を渡したとき、渡した側で調べたときと、関数内で調べたときと、変数のアドレスが違っていました。

DISPPARAMS構造体というのは、初めて聞いたのですが、これなら納得がいきます。

GetWindowsDirectoryAなどのAPIにBSTRを渡しているのに、ちゃんと文字列が得られるというのも、同時に納得がいきました。
投稿日時 - 2001-06-22 17:20:10
-PR-
-PR-

その他の回答 (全2件)

  • 回答No.1
レベル10

ベストアンサー率 42% (79/186)

あまり自信がないのですが・・・ >これは、VBが引数を渡す時点で変数A用のメモリ領域をかってに確保し、Nという変数の参照型を作ったということの証拠になります。 何をさして証拠といわれているのかちょっとわかりませんが、プロシージャの引数は、参照渡しがデフォルトであることはマニュアルに記載があります。(当然、値渡しもあります。) >参照型をもっと自由に使いたいと思い、参照型を作るAP ...続きを読む
あまり自信がないのですが・・・

>これは、VBが引数を渡す時点で変数A用のメモリ領域をかってに確保し、Nという変数の参照型を作ったということの証拠になります。
何をさして証拠といわれているのかちょっとわかりませんが、プロシージャの引数は、参照渡しがデフォルトであることはマニュアルに記載があります。(当然、値渡しもあります。)

>参照型をもっと自由に使いたいと思い、参照型を作るAPIを作ってみました。
どのような処理をすることをしたいのかはっきりしませんが、VBの仕様でプロシージャの引数以外に参照値を渡す(代入する)ことはできないような気がします。
当然、=演算子で代入することは仕様上できないと思います。

ところで、「参照型を作るAPI」というのは、言語は何で作られたのでしょうか?

VBで作るのであれば、クラスを作成し、クラス内で参照値を返すように見えるメソッドは作れるような気がしますが、VBは演算子のオーバーライドができないので、=演算子を使って操作できるようにはできないような気がします。
CやC++言語を使い、同じように作ることもできるような気はしますが、VB側で演算子のオーバーライドがやはりできないので、=演算子を使用することはできないと思います。
補足コメント
haporun

お礼率 77% (530/685)

関数はバリアント型の参照をほしがっているのに、Longの変数が渡せること自体が、C++から考えるとおかしなことだということです。
要は、VBでは、Cのように関数を呼び出すときに、スタックのpush、pop、callだけを行っているのではなく、mallocを使ったり、Variant構造体の内部をいじったりしているといいたいのです。

参照型をもっと自由に使いたいというのは、

Dim A As Variant, B As Long
MakeRef A, B

とすれば、AがBの参照になるような関数を作りたいと言うことです。
C++では次のようにすれば簡単ですが。

long B;
long& A = B;

ちなみに、APIを作る環境は、C++のWin32 DLLです。
投稿日時 - 2001-06-22 14:31:58


  • 回答No.3
レベル10

ベストアンサー率 42% (79/186)

APIを作るということの解決案にはなりませんが、補足から勝手になぜそのようにしたいかを推測しました。 >Dim A As Variant, B As Long >MakeRef A, B とし、Aを変更すればBも勝手に変わる、またはその逆をしたいのでしょうか? もしそうであるなら、やはりクラスを作成しするのがいいように思います。 Dim obj1 as Object ...続きを読む
APIを作るということの解決案にはなりませんが、補足から勝手になぜそのようにしたいかを推測しました。

>Dim A As Variant, B As Long
>MakeRef A, B

とし、Aを変更すればBも勝手に変わる、またはその逆をしたいのでしょうか?
もしそうであるなら、やはりクラスを作成しするのがいいように思います。

Dim obj1 as Object
Dim obj2 as Object

Set obj1 = New ClassA
Set obj2 = obj1

とすれば、大丈夫なような気がします。

勝手な予想で、でしゃばって申し訳ありません。
お礼コメント
haporun

お礼率 77% (530/685)

それは一応私も考えてみました。
しかし、やっぱり、LongやDoubleの参照を作りたいわけです。

LongやDoubleのポインタを取得して、参照/代入を行うクラスも作ってみました。

最後にはやっぱりVariant型を懲らしめてやりたい(?)のです。
投稿日時 - 2001-06-23 11:25:42
このQ&Aのテーマ
このQ&Aで解決しましたか?
-PR-
-PR-
こんな書き方もあるよ!この情報は知ってる?あなたの知識を教えて!
このQ&Aにはまだコメントがありません。
あなたの思ったこと、知っていることをここにコメントしてみましょう。

その他の関連するQ&A、テーマをキーワードで探す

キーワードでQ&A、テーマを検索する
-PR-
-PR-
-PR-

特集


-PR-

ピックアップ

-PR-
ページ先頭へ