ab.com コミュニティ

ActiveBasicを通したコミュニケーション
現在時刻 - 2024年3月29日(金) 21:53

全ての表示時間は UTC+09:00 です




新しいトピックを投稿する  トピックへ返信する  [ 9 件の記事 ] 
作成者 メッセージ
投稿記事Posted: 2005年5月30日(月) 22:45 
いつもお世話になっています。

Class CTest
Public
Sub Test()
MsgBox 0,"Test"
End Sub
End Class
Dim pClass As *CTest
pClass=New [2] CTest
pClass[0]->Test()
Delete pClass

上のコードをコンパイルしようとすると、エラーが出ます。
それで、
pClass[0]->Test()
という行を
pClass[0].Test()
に変更すると動作してしまいました。
ポインタ参照であれば -> で参照すると認識しているので、これがバグなのか仕様なのかよくわかりません。


通報する
ページトップ
   
 記事の件名:
投稿記事Posted: 2005年5月30日(月) 22:46 
まだ、配列は勉強中ですが
配列のところを見るとDim宣言時にやっておいたほうがいいみたいです

Class CTest
Public
Sub Test()
MsgBox 0,"Test"
End Sub
End Class
Dim pClass[2] As *CTest
pClass[2]=New CTest
pClass[0]->Test()
Delete pClass


通報する
ページトップ
   
 記事の件名:
投稿記事Posted: 2005年5月30日(月) 22:47 
[]自体がポインタ参照の意味を含んでいると考えたらどうでしょうか。
Dim p As *DWord
p =new[7] DWord
たとえばこの場合もp[0]~p[7]と書けば要素にアクセスできます。
GetDWord(p[0])などとする必要が無いのと同じなんでしょう。


通報する
ページトップ
   
 記事の件名:
投稿記事Posted: 2005年5月30日(月) 22:47 
オフライン
Site Admin

登録日時: 2005年5月30日(月) 15:08
記事: 535
これは言語仕様です。

Dim pClass As *Ctest

という定義があったとすると、
pClassはオブジェクトポインタであり、
pClass[0]は実体オブジェクトであるという認識が必要です。
ポインタというのは、配列参照した時点で実体になるということですね。


違う例えをしてみると、

Dim pData As *Long

という定義では、

pDataはLong型ポインタですが、
pData[0]はLong型の値として扱いますね。オブジェクトポインタの配列参照についても、これと同じ解釈だと思ってください。


通報する
ページトップ
 記事の件名:
投稿記事Posted: 2005年5月30日(月) 22:47 
確かに、言われてみれば納得です。
素早い回答ありがとうございます。


通報する
ページトップ
   
 記事の件名:
投稿記事Posted: 2005年5月30日(月) 22:48 
気になる点が幾つかあるので、指摘しておきます。

>> 5938 (山本様)
> ポインタというのは、配列参照した時点で実体になるということですね。
例の添え字を使うポインタの指定方法って、配列参照というのですね。
それは、ポインタと配列は同等である、というスタンスでしょうか?
てっきり、ポインタと配列は、C言語同様、似て非なる全くの別物だと思い込んでいましたので、あれれって感じです。
僕が勝手にABにC言語の法則を適用してしまったのが、誤解の原因なのですが・・・

>> 5936 (イグトランス様)
> []自体がポインタ参照の意味を含んでいると考えたらどうでしょうか。
というか、本来添え字の角括弧はそちらの意味合いが強いようです。
添え字の使用方法を配列のみに留まらせずポインタ参照にまで拡大した、という解釈ですが、そのポインタと配列の非相互互換的な曖昧さが初心者がポインタのあたりでよくつまづく原因の1つだったりして。
前述の通り、ABでは配列とポインタが同等(らしい)なので、分かり易くていいですね。
ところで、ABはBASIC言語をベースにしているので、そういう意味もこめて、僕は配列指定時には丸括弧を使い、角括弧はポインタ参照の時のみに使用するというように、括弧を使い分けるよう心掛けています。

> GetDWord(p[0])などとする必要が無いのと同じなんでしょう。
揚げ足的で恐縮なのですが、「必要がない」のではなく、厳密には、通例「してはいけない」のです。
ただし、pが多重ポインタ派生していれば許されるのですが、現時点のABでは多重ポインタ派生はサポートされていないようです。言い換えれば、ポインタ派生は一次元までという制約があるということ。
無理矢理しようとすれば不可能ではないのですが、それはABの規格外プログラムです。
(注:巧みなコーディングをすれば、必ずしも規格外と断定できるわけではない旨も併せて述べておきます。)

>> 5935 (mako20様)
> 配列のところを見るとDim宣言時にやっておいたほうがいいみたいです
これには、落とし穴があります。Dimでは、配列の添え字番号に変数を指定できないのです。つまり、
Dim i As Long : i = 2
Dim p[i] As CTest
これは、文法上正しいのでしょうが、コンパイルエラーになります。
その点、New演算子は、添え字番号に変数を指定できます。
どういうことかというと、Dimで配列を定義できるのはコンパイル時に配列の要素数が確定している場合のみであり、それ以外の場合ヒープ領域を自分で確保して、先頭アドレスをポインタとして配列参照しなければなりません。
(注:状況によっては変数を指定しても確定する場合があります。例えば、定義した変数を初期値のまま二度と書き換えない場合など。上の2行のコードがまさしくその状況です。しかし、コンパイラはそこまで追ってはくれません。つまり、いかなる場合でもDimでは添え字に変数を指定してはいけないのです。)
基本型であれば(String型以外)実体のサイズが既知であるのでそれで問題ないのですが、クラスオブジェクト型は型サイズが未知ですので、どれだけメモリを確保すればいいか、プログラマは知る術がありません。
SizeOf関数は不可です。0が返ります。
だから、わざわざNew演算子が導入されたのですね。
そもそも何故New演算子が言語仕様として必要なのか、その理由を考えれば当然のことなのです。
余談ですが、先ほどの例外のString型、これはABが管理しているので配列化は考えない方が無難です。代わりに、BytePtr型の配列を使用することにより克服できます。
また、更なる余談ですが、Discoversoftは公にBytePtr型を使って文字列データを取り扱うことを推奨しています。
しかしながら、API関数に関わらない部分では、ABが自動管理してくれるString型は非常に便利です。
ケースバイケースで最適な型を選ぶ。無理にString型の使用を抑制するより、こちらのほうが賢明だと僕は思います。

また、No.5935中で示されたコードは、明らかにNew演算子の使用方法に間違いがあります。
----
> Dim pClass[2] As *CTest
> pClass[2]=New CTest
> pClass[0]->Test()
> Delete pClass
----
間違っているのは2行目と4行目、エラーは3行目と4行目です。

まずは2行目の間違いから説明します。
仕様では、New演算子は直後の添え字+1だけのオブジェクトを連続したメモリロケーション上に配置します。
今例では、2行目でNewの後ろに添え字が指定されていないので、生成するオブジェクトは1個だけです。
pClass[0] と pClass[1] はヌルポインタ、pClass[2]のみが実体を持つことになります。
こちらの試験ではこのプログラム、3行目までは正常に(?)動いちゃったのですが、断言します。これはバグです。本来、pClass[0]は実体を持たないヌルポインタなので、クラスのメンバにアクセスできません。
こういう動作はは往々にしてデバッグ作業を困難にするものです。
次期バージョンでの修正に期待しましょう。

次に4行目の間違いを説明します。厄介なことに、4行目では2つのミスが混在しているので、非常に解りづらいです。

まず1つ目。
> Delete pClass
再確認します。pClassは「CTest型のオブジェクトを指すポインタの配列[2]」という型でしたね。複雑な型名だ(^^;
詰まるところ、配列なわけです。で、配列の添え字を取り除くと何になるか。そう、配列の先頭要素へのポインタですね。
このコードでは、配列の先頭要素へのポインタが指すもの(つまり、その配列自体)をDeleteで破棄しようとしています。
でも、配列そのものはCTest型ではないので、Delete出来るはずもありません。
では、どうすればよいか。結局New演算子を使ってオブジェクトを複数生成するときは、Newの後ろに添え字を指定することになります。
あるいは、Forなどでループすれば添え字を使わなくてもいいのですが、非効率的です。また、このようにすれば破棄時にもループ等で個々に破棄しなければなりません。

2つ目。
Deleteでは、オブジェクトの実体へのポインタを指定します。
ですので、今例では
Delete pClass[0]
としなければいけません。

まとめると、次のような修正案が正しいコードです。(無理矢理Dimを使ったので、かなり不自然)
----
Dim pClass[2] As *CTest
For i = 0 To 2
pClass[i] = New CTest
Next
pClass[0]->Test()
For i = 0 To 2
Delete pClass[i]
Next
----

また、次のコードはNGです。こういうミスを犯さないでください。
----
Dim pClass[2] As *CTest
pClass[0] = New[2] CTest
pClass[0]->Test() ' これはOK
pClass[1]->Test() ' これはNG
pClass[2]->Test() ' これもNG
Delete pClass[0]
----


以上です。締め括りに、一回の書き込みで欲張ったためなかなかの長文になってしまいましたこと、および枝を入り組んだ構造にしてしまいましたことをお詫び申し上げます。


通報する
ページトップ
   
 記事の件名:
投稿記事Posted: 2005年5月30日(月) 22:48 
> 気になる点が幾つかあるので、指摘しておきます。
>
> >> 5938 (山本様)
> > ポインタというのは、配列参照した時点で実体になるということですね。
> 例の添え字を使うポインタの指定方法って、配列参照というのですね。
> それは、ポインタと配列は同等である、というスタンスでしょうか?
> てっきり、ポインタと配列は、C言語同様、似て非なる全くの別物だと思い込んでいましたので、あれれって感じです。
> 僕が勝手にABにC言語の法則を適用してしまったのが、誤解の原因なのですが・・・

私はABの配列とポインタはCのそれと全く同じだと思います。
山本様の話もポインタ変数には何らかの方法によってオブジェクトを指している状態を前提にしていると思われます。

> > GetDWord(p[0])などとする必要が無いのと同じなんでしょう。
> 揚げ足的で恐縮なのですが、「必要がない」のではなく、厳密には、通例「してはいけない」のです。
すみません。あいまいに書いては駄目ですね。


通報する
ページトップ
   
 記事の件名:
投稿記事Posted: 2005年5月30日(月) 22:48 
takさん、勉強になりました。
これを機会にわからないことがあった場合、いろいろと聞いてみたいと思います(同じABユーザーさんにも)

それと、BASIC言語にかなり詳しいですね。心強いです


通報する
ページトップ
   
 記事の件名:
投稿記事Posted: 2005年5月31日(火) 00:10 
> また、No.5935中で示されたコードは、明らかにNew演算子の使用方法に間違いがあります。
> ----
> > Dim pClass[2] As *CTest
> > pClass[2]=New CTest
> > pClass[0]->Test()
> > Delete pClass
> ----

> (中略)

> pClass[0] と pClass[1] はヌルポインタ、pClass[2]のみが実体を持つことになります。
> こちらの試験ではこのプログラム、3行目までは正常に(?)動いちゃったのですが、断言します。これはバグです。本来、pClass[0]は実体を持たないヌルポインタなので、クラスのメンバにアクセスできません。

前言撤回...力一杯バグだと断言してしまったので言い辛いのですが、これ、必ずしもバグだと否定できないようです。面目ない。
C++ではStatic修飾子を付加すれば許されますが、ABにはその機能はありませんので、やはり許されざるコーディングに変わりはないと思います。

...いや、しかし、Borland C++ や Visual C++ でも動くのなら、仕様なのかな?
今度はC#やJavaでも試してみようと思います。


通報する
ページトップ
   
期間内表示:  ソート  
新しいトピックを投稿する  トピックへ返信する  [ 9 件の記事 ] 

全ての表示時間は UTC+09:00 です


オンラインデータ

このフォーラムを閲覧中のユーザー: Ahrefs [Bot] & ゲスト[25人]


トピック投稿:  可
返信投稿:  可
記事編集: 不可
記事削除: 不可
ファイル添付: 不可

検索:
ページ移動:  
cron
Powered by phpBB® Forum Software © phpBB Limited
Japanese translation principally by ocean