いずれも地道に修正すれば済む話、あとはやる気の問題
また、#property strict関連の投稿です。しつこくてすみません。個人的にホットな話題なので、もう少しお付き合い頂ければ幸いです。
#property strictを追加するとハッピーになれることは、#property strictとコメント文の意外な関係やENUM(列挙型)を利用したEAパラメータ設定方法でお伝えした通りです。
でも躊躇しているともお伝えしました。理由は、既存のコードに修正が発生するためです。
具体的にどんな修正が必要になるの?どれくらい修正が必要になるの?ということで、オリジナルのライブラリ群を呼び出すだけのEAを作って試してみました。
その結果、「Result: 18 error(s), 147 warning(s)」というメッセージが。うぅ…。
気持ちが折れそうになりながらもメッセージ内容を分類してみたところ、以下の3つに大別できました。
- error 256: undeclared identifier
- warning 181: implicit conversion from ‘number’ to ‘string’
- warning 43: possible loss of data due to type conversion
正直、「面倒くさい!」という気持ちが強いのですが、メリットを享受するためだと思って、頑張って修正することにしました。
error 256: undeclared identifier
このエラーはちょいちょい発生しますね。「未定義の識別子があるよ」と書いてあります。識別子というのは乱暴に言えば、変数のことだと理解していれば大体OKです。
#property strictにより、変数の有効範囲(かっこよく言うならスコープ)がブロック({}で囲まれた範囲)内のみになったため、元々別のブロックで宣言していた同名の変数が別物として解釈され、結果として未定義の変数があるよと指摘されたわけです。
抽象的な説明だといまいちピンとこないと思いますので、例を用いて説明します。
double getGlobalVariables(string aName, int aMagic, string aSymbol="", int aTimeframe=0) { // 中略 if(GlobalVariableCheck(name)){ double result = GlobalVariableGet(name); } return(result); }
変数resultはif文ブロックで宣言されています。#property strict配下では、この変数はif文ブロック内でのみ有効になります。つまり、return(result)のresultとは異なる変数になるということです。
同姓同名の別人物になるんだと理解してください。
では、return(result)のresultは、どこで宣言されているか?というと、どこにも宣言されていませんね。そのため、undeclared identifierのエラーが発生したわけです。
この場合は、double result = 0.0;の一行をgetGlobalVariables()関数直下のブロックに置き、double result = GlobalVariableGet(name);のdoubleを削除してあげればOKです。
変数の有効範囲という概念はプログラミング特有のものなので、慣れるまでに時間がかかります。しかし、非常に重要な概念なので、ぜひこの機会にマスターしちゃいましょう!
warning 181: implicit conversion from ‘number’ to ‘string’
「数値から文字列への暗黙的な変換が行われたよ」と書いてあります。
先程と同様に、例で説明します。
double getGlobalVariables(string aName, int aMagic, string aSymbol="", int aTimeframe=0) { string name = aName + "_" + aMagic; // 中略 }
aMagicは整数型intの変数ですが、aName + “_”という文字列と結合しています。数値と文字列はそのままでは結合できないため、メタエディターが「旦那、整数を文字列に変換しときやしたよ」と気を利かせてくれたわけです。なかなか良い奴ですね。
この場合は、IntegerToString()等の型変換関数やキャストを利用すれば良いでしょう。具体的には、string name = aName + “_” + aMagic;をstring name = aName + “_” + IntegerToString(aMagic);に変更すればOKです。
warning 43: possible loss of data due to type conversion
「型変換のせいでデータが欠落しちゃったかも」と書いてあります。
メタエディターはほんとに親切です。かもしれないことまで教えてくれます。
やはり、ここも例で説明します。
int orderSendReliable(string aSymbol, int aCmd, double aVolume, double aPrice, int aSlippage, double aStoploss, double aTakeprofit, string aComment = NULL, int aMagic = 0, datetime aExpiration = 0, color aArrow_color = CLR_NONE) { // 中略 double digits = MarketInfo(aSymbol, MODE_DIGITS); aStoploss = NormalizeDouble(aStoploss, digits); aTakeprofit = NormalizeDouble(aTakeprofit, digits); // 中略 }
変数digitsは浮動小数点型(double)です。NormalizeDouble()の2番目の引数は整数型で渡す決まりになっています。整数型の数値を渡すべきところを浮動小数点数型の数値を渡してしまっているわけです。
浮動小数点型の数値を強引に整数型として渡したため、数値の一部が欠落しちゃったかもと教えてくれているわけです。
スーファミのソフトを強引にファミコンで起動させたから、色とか音とかの情報が欠落しちゃったかも的な感じでしょうか。
この場合は、適切な型になるようにキャストを利用すれば良いでしょう。具体的には、double digits = MarketInfo(aSymbol, MODE_DIGITS);をint digits = (int)MarketInfo(aSymbol, MODE_DIGITS);に変更すればOKです。
無論、これが許されるのは異なる型の数値に変換しても実害がない場合に限ります。例えば、浮動小数点数型の円周率3.14を何かの関数の整数型の引数に強引に渡した場合、0.14が欠落してしまうので、意図しない挙動になる可能性があります。この点は十分に注意しましょう。
上記の例の場合は、digitsは浮動小数点数型の3.0とか5.0になった後、キャストで整数に変換して3とか5になります。小数点があってもなくても変わらないですよね。だから実施しても問題ないのです。