【(VB6)配列データの扱いについて】

以下のような流れのコーディングをしました。

流れ1:メソッドAからForm1のSetDataを呼び出し、配列を渡す
流れ2:Form1は受け取った配列をグローバル変数に設定する(イメージは以下の通り)。

 Dim Array() As String

 Public Sub SetData(BayRef input_Array() As String)
  Array = input_Array
 End Sub


流れ3:ユーザの操作に応じて配列を修正する。

 Private Sub ボタン1クリック()
  Array(0)="ボタン1が押されました"
 End Sub

 Private Sub ボタン2クリック()
  Array(0)="ボタン2が押されました"
 End Sub


Form1が終了したとき、メソッドAで渡した配列も更新されることを期待したのですが
更新されませんでした。
以下のようにArrayを受け取るためのメソッドを用意したら配列を受け取ることができたのですが、、、、
出来ればForm1で設定したとおりに、メソッドAの配列が自動的に更新されるのが好ましいです
(ポインタのようにデータを直接編集できる方法とあると嬉しいです)。

コーディング方法についてアドバイスいただきたく宜しくお願いします。

 Public Sub GetData()As String()
  GetData = Array
 End Sub

回答の条件
  • URL必須
  • 1人2回まで
  • 13歳以上
  • 登録:2010/03/17 14:12:44
  • 終了:2010/03/23 10:14:13

ベストアンサー

id:mj99 No.4

mj99回答回数138ベストアンサー獲得回数382010/03/17 23:27:35

ポイント200pt

すでに回答されているとおり、VB6の代入式は「複製」を作ることと同じです。

プロシージャの引数をByValとした場合も「複製」が作られます。


代入式は、単純な型(IntegerやString)だけでなく、ユーザ定義型(Type hoge~End Type)も複製します。

配列変数の場合は、配列のすべての要素が複製されます。


それに対し、

「オブジェクト型変数」は、代入で「複製」が作られず「参照」が作られます。

「参照」を作る場合は、単純に代入するのではなく、

Set A = B

のように、Setキーワードを指定します。


Setキーワードが使えるのは、イコールの両辺が「オブジェクト型」である必要があります

(オブジェクト以外を指定するとコンパイルエラーになる)


----

前置きが長くなりましたが、質問文にあるコードを「オブジェクト型変数=クラスモジュール」を使って書いてみました。

http://www.geocities.co.jp/SiliconValley-Bay/9960/vb/vbclass.htm...


クラスモジュールを一つ追加してください。

オブジェクト名(プロパティシートにある)は、"Class1"とします。

クラスモジュールに書くのはこんだけ

Option Explicit

Public msg As String


以下、フォームモジュールに書く

オブジェクト名は、"Form1"とします。(ちなみに、フォームモジュールはオブジェクト型の一種です)

コマンドボタンCommand1が配置してあるものとします。

Option Explicit

Private localDat As Class1

Public Sub setData(ByVal paramDat As Class1)
    Set localDat = paramDat
End Sub

Private Sub Command1_Click()
    localDat.msg = "押したよ"
End Sub


こんな感じで動作確認します。

Command1のクリックあと、フォームを閉じると、dat.msgが書き換えられるのが確認できると思います。

    Dim dat As New Class1
    Dim frm As New Form1
    
    dat.msg = "押してないよ"
    Call frm.setData(dat)
    frm.Show vbModal
    
    MsgBox dat.msg


----

ここで、

Form1のsetDataメソッドの引数はByValだから、複製が作られるんじゃないのか?

というツッコミがあったりします。

プロシージャの引数がオブジェクト型の場合、

ByValは参照渡しで、

ByRefは参照の参照渡し(C言語で言えば、ポインタのポインタ)

に、なります。

その他の回答(3件)

id:ko8820 No.1

ko8820回答回数1221ベストアンサー獲得回数692010/03/17 14:20:27

ポイント50pt

標準モジュールに書かないとグローバル変数になりません。

Form内に書くと、スコープがForm内のグローバル変数になります。

http://q.hatena.ne.jp/answer

id:harunoharuno

『グローバル変数』すいません。言い方間違えました。

確かに標準モジュールに書けば可能な気がしますね。

個人的にはC言語のようにポインタを渡してForm1でポインタが指し示す先を編集するという

のが理想なのですが、そのようなコーディングはできないものでしょうか?

2010/03/17 14:28:12
id:HALSPECIAL No.2

HALSPECIAL回答回数407ベストアンサー獲得回数862010/03/17 14:58:55

ポイント50pt

この部分で、ディープコピーになってしまっていると思います。

Array = input_Array

呼び出し元のフォームから、配列を取得にいくか、

呼び出し元のフォームにもGetDataメソッドを作ってセットしてあげるかしないとダメだと思います。

id:harunoharuno

VBコーディングの一般的な記法がわからないので参考になります。

ディープコピーとは、値渡しのことですね(もし違ったら再回答よろしくおねがいしますm(_ _)m)。

2010/03/17 15:04:23
id:Km1967 No.3

Km1967回答回数224ベストアンサー獲得回数352010/03/17 17:40:52

ポイント50pt

Array = input_Array

これは単に値を渡してるだけだからのぉ。VBでは他の言語のように変数に対して直接、参照とかエイリアスといったような設定を行う事は出来ん。構造体うんぬんの話もでてくるかもしれんが、個別に作成されて統一感の無い多数のフォームを楽して扱いたいといったような向きの相談だろうから多分違うだろう。楽する方法は無いなぁ。


自力で探し出されたようだがMicrosoftのサポートにも載っておるので参照しておいたほうがよかろう。

「Visual Basic では、変数のアドレスを取得する方法」

http://support.microsoft.com/kb/199824/ja

id:mj99 No.4

mj99回答回数138ベストアンサー獲得回数382010/03/17 23:27:35ここでベストアンサー

ポイント200pt

すでに回答されているとおり、VB6の代入式は「複製」を作ることと同じです。

プロシージャの引数をByValとした場合も「複製」が作られます。


代入式は、単純な型(IntegerやString)だけでなく、ユーザ定義型(Type hoge~End Type)も複製します。

配列変数の場合は、配列のすべての要素が複製されます。


それに対し、

「オブジェクト型変数」は、代入で「複製」が作られず「参照」が作られます。

「参照」を作る場合は、単純に代入するのではなく、

Set A = B

のように、Setキーワードを指定します。


Setキーワードが使えるのは、イコールの両辺が「オブジェクト型」である必要があります

(オブジェクト以外を指定するとコンパイルエラーになる)


----

前置きが長くなりましたが、質問文にあるコードを「オブジェクト型変数=クラスモジュール」を使って書いてみました。

http://www.geocities.co.jp/SiliconValley-Bay/9960/vb/vbclass.htm...


クラスモジュールを一つ追加してください。

オブジェクト名(プロパティシートにある)は、"Class1"とします。

クラスモジュールに書くのはこんだけ

Option Explicit

Public msg As String


以下、フォームモジュールに書く

オブジェクト名は、"Form1"とします。(ちなみに、フォームモジュールはオブジェクト型の一種です)

コマンドボタンCommand1が配置してあるものとします。

Option Explicit

Private localDat As Class1

Public Sub setData(ByVal paramDat As Class1)
    Set localDat = paramDat
End Sub

Private Sub Command1_Click()
    localDat.msg = "押したよ"
End Sub


こんな感じで動作確認します。

Command1のクリックあと、フォームを閉じると、dat.msgが書き換えられるのが確認できると思います。

    Dim dat As New Class1
    Dim frm As New Form1
    
    dat.msg = "押してないよ"
    Call frm.setData(dat)
    frm.Show vbModal
    
    MsgBox dat.msg


----

ここで、

Form1のsetDataメソッドの引数はByValだから、複製が作られるんじゃないのか?

というツッコミがあったりします。

プロシージャの引数がオブジェクト型の場合、

ByValは参照渡しで、

ByRefは参照の参照渡し(C言語で言えば、ポインタのポインタ)

に、なります。

  • id:harunoharuno
    これを使えばなんとかなるのかなぁ。
    http://www.geocities.co.jp/SiliconValley-Bay/9960/vb/pointer.html

    確認は時間があるときに行う予定。
  • id:mj99
    >> これを使えばなんとかなるのかなぁ。
    >> http://www.geocities.co.jp/SiliconValley-Bay/9960/vb/pointer.html

    確かにVarPtrで"変数のアドレス"を取得することはできますが、
    "変数のアドレス"から"VBの変数"を作る方法は無いんですよね。。。
    そのURLにあるサンプルは、"変数のアドレス"を使ってVB6の変数を「複製」する方法を解説している。
  • id:harunoharuno
    >>mj99様

    コメントありがとうございます。
    ご指摘の通り『変数のアドレス"から"VBの変数"を作る方法』
    が見つからず、VarPtrを用いた方法は頓挫しました。

    オブジェクト型(クラス)を用いてのデータ更新の方法についても
    詳しく教えていただきどうもありがとうございました。

    『なるほど納得!』といいますか、まだ
    『オブジェクト変数を用いて、Setキーワードをツカエバイイノカー』といった理解です。
    まだあまり馴染んでいません。ですが、大変参考になりました
    今後は積極的に利用していきたいと思います。

    また、宜しくお願いします。

この質問への反応(ブックマークコメント)

「あの人に答えてほしい」「この質問はあの人が答えられそう」というときに、回答リクエストを送ってみてましょう。

これ以上回答リクエストを送信することはできません。制限について

絞り込み :
はてなココの「ともだち」を表示します。
回答リクエストを送信したユーザーはいません