FreeBASIC マニュアルのトップに戻る

FreeBASIC TutConstQualifiers

目次→教本→いっしょに学ぼうConst Qualifiers and You←オリジナル・サイト

Const 限定子(修飾子) 左にメニュー・フレームが表示されていない場合は、ここをクリックして下さい

←リンク元に戻る プログラム開発関連に戻る

注意: Const 限定子(修飾子) は、範囲の使い方と同様に、理解するのが少し難しいかもしれません。
このため、Const 限定子(修飾子)を理解しようとする前に、変数の範囲について、徹底的に理解して下さい。
変数の範囲
変数の範囲への序論

この項目の英文のタイトル「Const Qualifiers and You」は、決まり文句の表現として使っています。

Const 限定子(修飾子)は、一体全体何ですか?
これは、C++ の標準部品です。そして、FreeBasic にも存在します。
Const 限定子(修飾子)は、保護のさらにもう一つの形です。 - Const 限定子(修飾子)は、"変数" を、プログラムのある部分で、定数のように行動させます。言い換えれば、プログラムのいくつかの部分は、"変数" にアクセスします(読みます)が、"変数" を変更できません。
ただ、別の種類の、安全な型、本当の、しかし、非常に役に立つものです。
特に、これは、OO 状況で、非常に役に立ちます。OOP に関心がなくても、たぶんある程度、この利益を得ることができます。

FreeBasic の Const 限定子(修飾子)は、本質的にはデータ型宣言への拡張です。そして、これは、Dim、UDT メンバー、および手続きパラメタと共に、使います。
一般に、変数のデータ型宣言の "As" 部分の直後に、これを置きます:

Dim As Const Integer my_const_int = 5


(ところで、このチュートリアルの中で、私は例として Integer と Integer Ptr だけを使います - しかし、Const 限定子(修飾子)は、他のすべての変数の型で同じように動作します。Type、Enum、何かを宣言する他の何ものでも、かまいません。
何かでうまく行かないならば、それはたぶん FreeBasic のバグなので、それを報告して下さい。)

Const 限定子(修飾子) を使う場合、私たちがこれを作成するときに、一度これを変えることができることに、注意してください。
しかし、いったん変更した後は、もうそれを変えることができません。
実際、あなたはそれを初期化しなければなりません。 - 初期化しないと、コンパイラはエラーを表示します。(面白いことに、それに、"Any" を代入できます。そこでは、内容は保証されないで、何でもありえます。)
しかし、その後に、あなたはそれを変更する何もできません。
例えば、あなたが下のようすると、これは、実際に、エラーになります:

my_const_int = 3


しかし、下は、変数を、他の何ものにも変えないので、できます。

Print my_const_int


現在、これはすべてとても良いです。しかし、これは、Const の正常な使用法と、それほど異なるようには、見えません。
すなわち、下の2つの行は、今までのところ、実際上、同じものを意味するように思えます:

Dim As Const Integer my_const_int = 5
Const my_int As Integer = 5


Do they? Not quite.
Const 限定子(修飾子)は、変数として作動するが、変更できない const を作成します。
これは、Type や他の場所に、Const 限定子(修飾子)を置くことができることを意味します。
その上、Sub/Function 宣言で、Const 限定子(修飾子)を置くことができます。そして、これは Const 限定子(修飾子) が有効である、主要な理由です:

Sub my_sub (some_num As Integer)
End Sub


通常、関数は、関数に送られた変数を、変更できます。
もちろん、関数が、元の変数を変えるか、変数のローカルのコピーを変更するかどうかは、ByValByRef の使用によります。(もちろん、ポインタは、全体で別物です。) しかし、通常、関数は、変数を変えることができます。
これは、何かの理由で、望ましくない場合があります。Const 限定子(修飾子)は、変数が変わることを防ぐために、存在します。
上で与えられた関数では、関数は、some_num を変更できます。
通常、変更されるのは、ローカルのコピーにすぎないでしょう。これは、オリジナルの Const Integer に影響しないので、よいことです。しかし、下のように関数を宣言すると、どうなるでしょうか?

Sub my_sub (ByRef some_num As Integer)
End Sub


今、my_sub は、関数に渡されたどんな変数にも、直接アクセスします。このため、この種類のことができないようになっています。

my_sub (my_const_int)


なぜですか?
単に、関数が変数を変更するかもしれないからです。
もちろん、関数が、変数を確かに変更するかどうか、分かりません。しかし、変更するかもしれません。それで、できないようになっています。
実際、これをコンパイルしようとすると、"Invalid assignment/conversion." のエラーになります。
それは、変数の渡し方が ByRef であるときにだけ、ほとんど、あたかも、Const Integer が、別の変数の型であるかのようです。
この場合、変数の渡し方は、文字列を整数引数(逆もまた同様である)に渡そうとするように、行動します。
しかし、ByRef で渡していないなら、問題ありません。関数は、変数を変更できないからです!

そして、もちろん、下のようにするなら:

Sub my_sub (ByRef some_num As Const Integer)
End Sub


次に、これは問題なくコンパイルされますが、関数の中で下のようにしようとすると、エラーになります:

some_num = 3


なぜですか?
もう一度、元の変数は、ByRef で、sub に渡されたからです。
変数は現在、ローカルの範囲にありますが、渡し方が ByRef なので、変数へのどんな変更も、オリジナルを変更します。これは、できないことです。
もう一度、変数のコピーを作成すれば、変数の内容を好きなように変更することは、完全に可能です。

Dim As Integer copy_of_some_num = some_num
copy_of_some_num = 3


しかし、あなたは、some_num 自身を変更できません!

次に、私たちはポインタの話題に移ります。
ポインタはどうですか?
ポインタに関しては、それはもう少し複雑です。
ポインタ自体を Const として宣言することは、可能です。あるいは、ポインタが示すものを Const として宣言する、あるいは、両方とも Const として宣言することさえ可能です!
それで、下のすべてが有効です:

Declare Sub my_sub_a (ByRef ptr_A As Const Byte Ptr)

Declare Sub my_sub_b (ByRef ptr_B As Byte Const Ptr)

Declare Sub my_sub_c (ByRef ptr_C As Const Byte Const Ptr)


1番目は、ポインタ自体を、好きに変えることができます。しかし、ポインタが示すデータを変えることはできません。(たとえ、ポインタがポイントするものを変えたとしてもです。)
2番目は、ポインタが示すものを変えることができます。しかし、ポインタを他の何かに変えることはできません。
3番目は、ポインタが示すものも、ポインタ自体をも、変えることができません!
すべての場合で、あなたはポインタのコピーを作ることができます。 - しかし、それは、Const Integer Ptr か Const Integer Const Ptr でなければなりません。そうでないと、あなたは、オリジナルのポインタが示す内容を、何でも変えることができてしまうからです。
これは、変更されるもの全てに対して、強力な保護になります!

Const 修飾語の振る舞いについて、必ずしもよく分からないでしょうから、私は、許可するのに何が安全か、何が安全でないかを、決定する方法を、正確に説明しましょう。
これは、実はかなり簡単に要約することができます:
Const 限定子(修飾子)は、オリジナルのデータを保護することを目的としています。
Const 限定子(修飾子)は、データをコピーしたり、あるいは、コピーを変更することは、一切気にかけません。Const 限定子(修飾子)は、ただオリジナルのデータを変えないようにします。
これを覚えておくと、あなたは大いに助かるでしょう。
もちろん、オリジナルのデータが何か、を知る必要があります。 関係するポインターがあるとき、とても多くの異なる場所に、Const 限定子が置かれていることがあるからです。 (あなたは、どれだけのポインターがあるかに依存しますが、Const 限定子を何箇所でも設定できます!)
Const 限定子(修飾子)が、何のためのものか覚えている限り、それを置くべき場所を見つけるのに苦労しないでしょう。すべてでそれを必要としても。あるいは、それを使う必要がない場合も。

あなたは、また、UDT で、Const 限定子(修飾子)を使用できます。
いやむしろ、これは実際に OOP で、非常に重要なものです。(名前空間は、OOP の直接の部分ではないけれども、OOP にたいへん関係づけられています。その名前空間と同様の関係です。)
しかし、OOP を使わなくても、まだあなたの Types で、Const 限定子(修飾子)を使用できます。
私は本当に、例を示す必要さえありません。これがどのように働くかは、今、かなり明らかだからです。しかし、あなたのために、下に例を示します:

Type my_type
  As Const Integer t_int= 5
End Type

Dim As my_type t

t.t_int = 3


そして、明らかに、これはコンパイルされません。メンバー t_int が Const だからです。
その上、あなたは、また、Const 限定子(修飾子)で、この型 (この場合 t ) の変数を宣言できます。
t のすべてのメンバーが Const なので、下のコードは、コンパイルされません:

Type my_type
  As Integer t_int= 5
End Type

Dim As Const my_type t

t.t_int = 3



事態の OOP の部分に関して、その方法について知りたいと思うでしょう。(OOP に関心がないなら、この部分をスキップして下さい。)
メソッドは、これが呼ばれるとき、オブジェクトを暗黙で ByRef で渡します。
定数のオブジェクトを作る方法がありますか?
もちろん! 私たちは既にそれを見ました。
しかし、いくつかのオブジェクトのメソッドは、オブジェクトを変更するでしょう。そして、いくつか変更しないでしょう。
区別がありますか?
答えは、はい です。
2007年11月23日現在、私たちは、Const 手続きを使うことができます。
これは、あなたが以下のようにできることを意味します:

Type my_object
  Public:
    Declare Sub modifier_sub ()

    'オブジェクトを変更しない Sub は、Const 宣言します...
    Declare Const Sub non_modifier_sub ()
  Private:
    some_num As Integer = 3
End Type

Sub my_object.modifier_sub ()
  This.some_num = 3
End Sub

Sub my_object.non_modifier_sub ()
  Print This.some_num
End Sub

'Const オブジェクトだけは、初期化しなければならないことに注意してください。
'(この場合は、非 Const オブジェクトもまた初期化されるでしょうが)
'ちょうど、変数と同じです。
'したがって、オブジェクトのための Constructor を持たせるか、あるいは、
'すべての変数に、デフォルトの初期値を与えなければなりません。(私がここでしたように)
'この場合、コンパイラは、あなたのためにデフォルト構築子を作ります。
Dim As Const my_object t = my_object
Dim As my_object u

'これらの両方とも、コンパイルされるでしょう:
t.non_modifier_sub ()
u.non_modifier_sub ()

'...しかし、下の2つの、1番目は、コンパイルされないでしょう!
'Const オブジェクトの、非 Const メソッドは、呼ばれないかもしれないからです。
t.modifier_sub ()
u.modifier_sub ()

'私たちが結果を確認するまで、止まって(眠って)ください
Sleep


もう一度、これが働く方法は、簡単な規則に基づいています。
これの、暗黙で渡されたコピーは、ByRef で渡されるので、メソッドは、通常、オブジェクトの内容を変更できます。
そして、オブジェクトが As Const で宣言されていると、変更されることは起こるべきではありません!
これに対応するために、本質的に、2種類の方法があります。
この 2種類は、C++ドキュメンテーション・ページで、名前を与えられています。(下の参照に記載されています。):
mutator (変更子:突然変異誘発因子)と、inspector (調査器) です。
mutator (変更子:突然変異誘発因子) はオブジェクトを変更するかもしれません。しかし、inspector (調査器) は変更しません。
したがって、As Const と宣言されたオブジェクトに、これらのオブジェクトのために、inspector (調査器) メソッドだけを使用できます。すべてのメソッドが、非 Const オブジェクトのために呼ばれるかもしれないとしても。
inspector (調査器) メソッドは、もちろん Const メソッドとして宣言されたものです。
したがって、Const オブジェクトだけのために、これらの Const メソッドは使われるかもしれません。

これは、すべて非常に良いのですが、しかし、あなた方の何人かは尋ねるかもしれません - これがなぜ必要ですか?
はい、直接の答えは、このチュートリアルの *範囲* (えっ?) の外にあるでしょうから、私は反対質問します。 - いったいなぜ我々は範囲を必要とするのですか?
Const 限定子(修飾子) (および、将来の Const メソッド)の理由は、手続きやモジュールの範囲と同じ理由です。そして、オブジェクトで変数を隠すためと同じ理由です:
我々は、何かが変わることを、想定しない場合に、その何かが、プログラムの最中に予想外に変わらないことを確信していたいからです。
もちろん、私たちは、変化するものが欲しいときもあります。そして、それは、私たちが Const 限定子(修飾子) を使わない時です。
しかし、何かが、そのままで留まっていて欲しいときに、Const 限定子(修飾子)を使用します。そして、それが変化しないことを確信していることができます。(変化が起こる危険があれば、コンパイラは、コードをコンパイルしません!)
これが Const の定義、どう働いているかということです。そして、これは、あなたが Const を使う理由です!
そして、一般に、これは、範囲の制御やデータ隠蔽を使う、全ての理由です。


いくつかの最終的な注意
Const 限定子(修飾子)は、これが比較的新しい特徴であることを覚えておいてください。
何が「間違っているか」、あるいは「正しいか」について、私たちに伝えるドキュメンテーションは、ほとんどありません。このため、いくつか試してみるしか、しかたがない部分があります。
もし、これが、すべきでない動作をする(あるいは、これがするべき動作をしない)と感じたら、必ず、フォーラムに、報告してください!
それが、他の誰にとっても問題と考えられるなら、バグレポートを提出してください。
しかし、一般に、ちょうど私が言ったように動くはずです。そして、これまでに提示したすべての例は、私が述べたように動作するはずです。(私が言ったように、コンパイルされ、私が言ったように、コンパイルされません。)
覚えておいてほしい一番重要なことは、これを書いている時点では、最新の公式のリリースにない、ということです。 - あなたは、これが動く、最新の Subversion (サブバージョン、SVN) リリースを持たなければなりません。
(ここで挙げた例で、私が、コンパイルできる、と伝えたのに、コンパイラーがエラーを表示する場合は、あなたは、より新しいバージョンを必要とすることを意味します。)

Const 限定子(修飾子)について、他に何か苦労があれば、これについてのドキュメンテーションはありませんが、フォーラムには、このことについて知っていて、理解している多くの人々がいて、どんな質問についても助けることができることを、思い出してください。

まだ Const 限定子(修飾子)を理解できないなら、あなたは、たぶん初心者で、範囲に関して、まだとにかくあまり知らないのでしょう。なにも問題はありません。あなたは、プログラムを作っているうちに、順に学ぶでしょう。
最終的には、この特徴のための、何らかのきちんとしたドキュメンテーションが作成されるでしょう。それまで、これはあなたが持っているすべてです。
心に留めて下さい:
Const 限定子(修飾子) がどのように働いているかを理解していないと、あなたはたぶんこれを必要としないでしょう。
これらが、私の身近になるずっと前に、私は個人的に、すばらしいプログラムを書きました。私は、恐らく、これらが必要ではないところでは、今後も使うことなく、続けるつもりです。
これらが役に立つ、特定の場合があります。そして、その場合には、これらの例を理解して、これらを使うほうがよいです。
しかし、あなたが分からないなら、それはそれで良いことです!

最後に、下に、いくつかの役立つリンクを置きます。
1番目は、C++ドキュメンテーションページで、もちろん C++ の Const 限定子(修飾子)に関するものです。あなたが C++ を理解している場合にだけ、理解できます。そして、また、ここでは、私たちがまだ持っていないもの(すなわち、Const メソッド)に関しても、話しています。 それにもかかわらず、何か C++ を知っているなら、これを始めるすばらしい場所なので、よければ調べてください。
2番目は、私が、FreeBasic 開発(そして、Const 限定子(修飾子)に関する学習)に関して、フォーラム話題に尋ねたリンクです。
最後は、オリジナルの SourceForge Feature Request ページです。Const 限定子(修飾子)が、特徴として要求されたリンクです:

https://isocpp.org/wiki/faq/const-correctness
https://www.freebasic.net/forum/viewtopic.php?t=9975&postdays=0&postorder=asc&start=0
http://sourceforge.net/tracker/index.php?func=detail&aid=1480621&group_id=122342&atid=693199

いっしょに学ぼう に戻る
←リンク元に戻る プログラム開発関連に戻る

ページ歴史:2019-02-26 08:27:58
日本語翻訳:WATANABE Makoto、原文著作者:NoTthecheatr

ホームページのトップに戻る

表示-非営利-継承