開発環境 VC++ Ver6.0 SP6 MFC
マシンOS Windows XP HOME(最終的にはXP Pro)
上記環境で、ダイアログベースのアプリを作成しております。
設定値をINIファイルから読み込むのに、数が多いため配列にポインタを入れてループで
読み込みをしようと思っています。
class CSetOvParam : public CDialog
{
public:
UINT m_MotorEnd;
UINT m_RingClamp;
UINT m_UnloadArm1;
UINT m_UnloadArm2;
UINT m_UnloadChack;
UINT m_CommImage;
protected:
typedef struct setparam{
char EntryName[32]; // INIファイルEntryName
UINT *m_ptrParams; // 各設定Pointer
}SetParam;
};
SetParam m_SetParam[6] = {
{msgUnloadArm1, &m_UnloadArm1},
{msgUnloadArm2, &m_UnloadArm2},
{msgRingClamp, &m_RingClamp},
{msgUnlaodChack, &m_UnloadChack},
{msgCommImage, &m_CommImage},
{msgMotorEnd, &m_MotorEnd)}
};
BOOL CSetOvParam ::OnInitDialog()
{
CDialog::OnInitDialog();
GetCurrentDirectory( MAX_PATH, m_dir );
wsprintf( m_inifile, %s%s, m_dir, \\Params.ini );
for(i=0;i<6;i++){ // INIファイル設定値の読み込み
*(m_SetParam[i].m_ptrParams) = GetPrivateProfileInt
(SlotSetting,m_SetParam[i].EntryName,1,m_inifile);
}
UpdateData(FALSE); // ダイアログへの反映
}
上記のプログラムをコンパイルするとエラーが出てしまいます。
error C2146: 構文エラー : ';' が、識別子 'm_OvTimeParam' の前に必要です。
error C2501: 'OvTimeParam' : 識別名を宣言するのに、型が指定されていません。
fatal error C1004: 予期せぬ EOF が検出されました。
エラー発生箇所は配列宣言の一番最初で起きています。
VC++にはまだ不慣れなため、何が原因か解りません。
配列をメンバ関数内で宣言すると、コンパイルエラーも発生せず、意図したとおりの動
作をするのですが、なにせ実際の処理で読み込む設定値がかなり多く、また、読み込み
処理だけでなく、書き込み処理やデータチェックも必要なため、それぞれのメンバ関数
内で配列宣言などしていられません。
どなたか、上記プログラムのどこに間違いがあるのか、どうすればいいのかをご教授い
ただけませんでしょうか。
クラスの外では、SetParamやm_UnloadArm1などが何者か分かりません。
CSetOvParam::SetParam などとする必要があります。
しかし、SetParamはprotectedなため、クラス外からは見えないでしょう。
この関数でしか使わないのであれば、
グロバールにせずに、CSetOvParamのメンバ変数にしたらどうですか?
(場合によっては、staticやconstで修飾)
それならば、全てのメンバ関数で参照できます。
# C++では通常、構造体(クラス)のtypedefをする必要はありません。
# m_は、メンバ変数を表す接頭語ですので、グローバル変数には付けません。
訂正です・・・
>この関数でしか使わないのであれば、
このクラスでしか使わないのであれば、
>error C2146: 構文エラー : ';' が、識別子 'm_OvTimeParam' の前に必要です。
m_OvTimeParam って何?どこにもないですけど。
っていうか基本ができていないとしか思えない。メンバ変数がいったいどういう代物なのか
理解していますか?判っていたらそんなコードを書こうとはしないはずです。
どう直せばいいかは、どうしたいのか次第なのですが、コードから意図が読めない
(あまりにも間違いすぎててどう解釈すればいいのか)
ので、何がしたいのかを説明してください。
# メンバのデータ自体を配列で持って、enum なインデクスで参照するとか駄目ですか...。
# メンバがpublicな時点で個人的には....
今のままだと、メンバ変数を保持するインスタンスが特定できません。
メンバ自体を static にすればとりあえず動くようには思いますが...、
それで意図道理になるのかは不明です。
class CSetOvParam : public CDialog
{
public:
static UINT m_MotorEnd;
static UINT m_RingClamp;
...
UINT CSetOvParam::m_MotorEnd;
UINT CSetOvParam::m_RingClamp;
...
tetrapod様
済みません、
error C2146: 構文エラー : ';' が、識別子 'm_OvTimeParam' の前に必要です。
は
error C2146: 構文エラー : ';' が、識別子 'm_SetParam' の前に必要です。
の間違いです。
テスト用に一部を切り出した時のメッセージと間違えました。
意図していることは、定義した配列を、複数のメンバ関数からアクセスしたいので、特
定の関数の外に出そうとしました。
>っていうか基本ができていないとしか思えない。メンバ変数がいったいどういう代物な
>のか理解していますか?判っていたらそんなコードを書こうとはしないはずです。
確かに、落ち着いて考えれば、メンバ変数をクラスの外から参照できるわけは無いので
グローバルは無理ですよね。
REE様
># C++では通常、構造体(クラス)のtypedefをする必要はありません。
済みません、ついこの間までCばかりだったので、ついCのつもりで書いてしまいまし
た。
>グロバールにせずに、CSetOvParamのメンバ変数にしたらどうですか?
これは、
class CSetOvParam : public CDialog
{
public:
UINT m_MotorEnd;
UINT m_RingClamp;
UINT m_UnloadArm1;
UINT m_UnloadArm2;
UINT m_UnloadChack;
UINT m_CommImage;
protected:
struct setparam{
char EntryName[32]; // INIファイルEntryName
UINT *m_ptrParams; // 各設定Pointer
};
const struct setparam m_SetParam[6] = {
{msgUnloadArm1, &m_UnloadArm1},
{msgUnloadArm2, &m_UnloadArm2},
{msgRingClamp, &m_RingClamp},
{msgUnlaodChack, &m_UnloadChack},
{msgCommImage, &m_CommImage},
{msgMotorEnd, &m_MotorEnd)}
};
};
にすればよいと言うことでしょうか。
上記プログラムで確認したのですが、
配列宣言部分で
error C2059: 構文エラー : '{'
error C2334: '{' の前に予期しないトークンがありました。関数の本体は無視されます
のエラーメッセージが出てしまいました。
済みません、まだC++初心者の為、よくわかっていません。
どうぞ、ご教授下さい。
Ban様
それぞれの変数は、エディットボックスからの定義した変数なのですが、勝手にstatic
に変えてもいいのでしょうか?
構文上、非staticの配列メンバ変数を初期化することは出来ません。
constをやめて、コンストラクタで一つずつ代入するしかないです。
>const struct setparam m_SetParam[6] = {
ちなみにこのstructは不要です。
REE様
>構文上、非staticの配列メンバ変数を初期化することは出来ません。
>constをやめて、コンストラクタで一つずつ代入するしかないです。
有り難う御座います。
コンストラクタに初期化処理を入れて実現させます。
う~ん、結構つらいなぁ。
>>const struct setparam m_SetParam[6] = {
>ちなみにこのstructは不要です。
きちんとC++の基礎部分を勉強し直します。
皆さん、有り難う御座いました。
non-static メンバ変数のアドレスは this relative なので &m_UnloadArm1 とはできない。
static メンバ変数なら &CSetOvParam::m_UnloadArm1 とできますが、
static にするってことは設計上の用途が変わるってことなので、
変えてよいかどうかの判断はMr.Booさんにしかできません。
# なんとなく static でもいいように憶測できるが、俺なら変えない。
ではどうすればいいか、ってことになりますけど、意図が想像の範囲なのでアレですけど
Ban さんの
># メンバのデータ自体を配列で持って、enum なインデクスで参照するとか駄目ですか...。
がとりあえず簡単だと思う。
メンバ関数なら & が適用できるので
void CSetOvParam::set_UnloadArm1(UINT val) { m_UnloadArm1=val; }
とか作っておいてメンバ関数のテーブルにするとかそういう手もあり。
> それぞれの変数は、エディットボックスからの定義した変数なのですが、
> 勝手にstaticに変えてもいいのでしょうか?
static はだめですね。
ただ、配列にすることは可能です。(ソースを編集すれば)
一応こういう方法もあり(動作未確認)
class CSetOvParam : public CDialog
{
(略)
protected:
struct setparam{
char EntryName[32]; // INIファイルEntryName
UINT CSetOvParam::*m_ptrParams; // 各設定Pointer
};
static const setparam m_SetParam[6];
};
// *.cppで
setparam CSetOvParam::m_SetParam[6] = {
{msgUnloadArm1, &CSetOvParam::m_UnloadArm1},
{msgUnloadArm2, &CSetOvParam::m_UnloadArm2},
{msgRingClamp, &CSetOvParam::m_RingClamp},
{msgUnlaodChack, &CSetOvParam::m_UnloadChack},
{msgCommImage, &CSetOvParam::m_CommImage},
{msgMotorEnd, &CSetOvParam::m_MotorEnd)}
};
BOOL CSetOvParam ::OnInitDialog()
{
CDialog::OnInitDialog();
GetCurrentDirectory( MAX_PATH, m_dir );
wsprintf( m_inifile, %s%s, m_dir, \\Params.ini );
for(i=0;i<6;i++){ // INIファイル設定値の読み込み
this->*(m_SetParam[i].m_ptrParams) = GetPrivateProfileInt
(SlotSetting,m_SetParam[i].EntryName,1,m_inifile);
}
UpdateData(FALSE); // ダイアログへの反映
}
訂正・・
>setparam CSetOvParam::m_SetParam[6] = {
CSetOvParam::setparam CSetOvParam::m_SetParam[6] = {
tetrapod様、Ban様、REE様
皆さん、色々なアドバイスを有り難う御座います。
お教えいただいた内容を元に、もう一度トライしてみます。
本当に有り難う御座います。