Top > OOobbs > 7

OOobbs/7

  • サマリ: 変数の型が不一致の場合の挙動について
  • 環境: Calc
  • 状態: 未解決
  • 投稿者: XD1?
  • 投稿日: 2004-01-29 (木) 11:59:56

質問

 毎度お世話になっています。ExcelからOOへ乗り換えようと悪戦苦闘(?)している者です。じつは、サブルーチンの挙動がおかしいと思われる所がありまして、調べてみました。結果的に型宣言が不完全だったのですが、極端に単純化しますと、下記のような状況だったんです。サブルーチンだけを見ると、変数kの計算結果は単純に2222になります。ところがkは、メインルーチンでは型宣言がないので浮動小数点短精度実数と自動的にみなされ、サブルーチンでは整数と型宣言されています。そこでMS Visual Basicでは、型の不一致でエラーが出て処置がとまります。とことがOOの場合、msgboxで11と表示されて終わります。どうやら、最初の2回だけ代入が実行され、それ以降は代入されないようです。

 型宣言が不意完全なのは、自分のミスともいえますが、この挙動・エラー対応はどうも納得しがたいものがあります。そこで、
(1)私は日本語Win Meでしたが、Win XpやLinux等の場合、どうゆう結果になるでしょうか? 試していただける方、いらっしゃいますでしょうか?
(2)型の不一致の場合、最初の2回だけ代入が実行され、それ以降は代入されないというのは、エラー対応としてどうも普通ではないような気がします。それとも、OOスタイルとしては、こんなものなのでしょうか? このあたりの事情、お分かりになりますでしょうか?

 変な質問かもしれませんが、よろしくお願いします。もちろん、メインルーチンでもkを整数と型宣言すれば、2222という正常な計算結果になります。

  Sub mainmain
  Call subsub ( 1 , 10 , 100 , 1000 , k )
  MsgBox k
  End
  End Sub
  
  
  Sub subsub ( a , b , c , d , k As Integer )
  k = a
  k = k + b
  k = k + c
  k = k + d
  k = k * 2
  End Sub

回答

  • はじめまして。Linuxで試してみましたが、同様の結果となりました。 -- パインツリー? 2004-01-30 (金) 01:47:00
  • ただし、subsub側の型宣言を外してみたら、正常な結果が出ました。 -- パインツリー? 2004-01-30 (金) 01:49:20
  • Oooの場合、変数型を何も宣言しないと、バリアント型という、万能型になるのですが、これが仇になっているのかも知れないです。 -- パインツリー? 2004-01-30 (金) 01:59:53
  • どうも。Windows XP でも同じ結果です。 TypeName 関数を使って変数の型を調べてみるといいかもしれません。 -- はにゃ?? 2004-01-30 (金) 02:23:09

と書きましたが,上記のコードをデバッグしてみると subsub 内で k は k = k + b で 11 になりその後の演算では変化しませんでした。

これは subsub 関数へ値を渡す際の挙動の違いによるもののような気がしたので,次のようにしてみました。

Sub mainmain
  Call subsub ( 1 , 10 , 100 , 1000 , k )
  MsgBox k
  End
End Sub

Sub subsub ( a , b , c , d , ByVal k As Integer )
  k = a
  k = k + b
  k = k + c
  k = k + d
  k = k * 2
End Sub

このようにすると k = k + c の演算で k = 111 になります。この挙動から,「最初の2回だけ代入が実行され、それ以降は代入されないようです」というのは変数の型の違いによるものではなくて参照の違いによるものと分かります。 2 回目以降の演算も行われているのです。これは以前もあったのですが,Function や Sub への値は特に指定しない場合にはデフォルトで「参照渡し」になります。「値渡し」にするには ByVal キーワードを使用します。

ByVal キーワードを使用して変更したものでは MsgBox に値が表示されないので sub を function に変更して

Sub mainmain
  k = subsub ( 1 , 10 , 100 , 1000 , k )
  MsgBox k
  End
End Sub

Function subsub( a , b , c , d , ByVal k As Integer )
  k = a
  k = k + b
  k = k + c
  k = k + d
  k = k * 2
  subsub = k
End Sub

とするべきかもしれません。変数のスコープが違えば別ですが。 -- はにゃ?? 2004-01-30 (金) 03:12:00

  •  みなさん、レスどうもありがとうございます。ByValについて、私としても改めてマニュアルを読みました。うーーん、このsubsubはa,b,c,dからkを計算するものですから、ByValを適用するとしたらa,b,c,dに対して、ということになるような気がします。とにかく、OSにかかわらずmsgboxで「11」という結果になるということですね。今のところ腑に落ちないにしても、この点(OOoスタイルとしてはこの変数型+参照法ではこの応答)を受け止めざるを得ないということでしょうか。subsubの"as integer"を消すと正しい「2222」となるのは、こちらも同じです。こうなると、逆説めいてきますが、型宣言のない変数にはある程度の融通が利くので、(文字変数などは別にして)数値変数に関してはよほどのことがない限り"as integer"などという型宣言をしない方が不具合が起き難いとも言えます。教科書的には、型宣言省略は良くないとも言えますが、、、、、 -- XD1? 2004-01-30 (金) 12:12:16


Reload   New Lower page making Edit Freeze Diff Upload Copy Rename   Front page List of pages Search Recent changes Backup   Help   RSS of recent changes