コンパイラはVC++2008です。
いろいろあって、あるクラスにおいて関数ポインタと関数オブジェクト双方を
同じように利用できないかと考えて、次のように試みました。
class Base
{
public:
virtual void func() =0;
};
template<class Func>
class CFunc :public Base
{
private:
Func m_func;
public:
CThreadFunc(Func func):m_func(func){}
void func(){m_func();}
};
class Hoge
{
private:
Base* base;
public:
template<class Func>
Hoge(Func func)
:base(new CFunc<Func>(func))
{}
~Hoge()
{
delete base;
}
void DoSomething()
{
base->func();
}
};
クラスをテンプレートにするといちいち指定しなければならないので、
まず基底クラスに適当な仮想関数を設け、それを継承したクラスをテンプレートにしました。
そしてコンストラクタの引数で何かしらを受け取って、オーバーライドした関数の中で
関数ポインタか関数オブジェクトだと仮定して呼び出しています。
さらに基底クラスのポインタを目的のクラスが保持してやり、
こちらはコンストラクタをテンプレートにすることで引数から型を推測してもらうことで
先ほどのテンプレートクラスのインスタンスを作成しています。
そしてポインタを介してfunc()を使ったり…、などすれば、
とりあえず引数なしの関数と関数オブジェクトを同等に扱えないかなと思ったからです。
で、このようなクラスを作成してコンパイルすると、
void func(); //何かしら処理する関数
class Function
{
public:
void operator ()(); //何かしら処理する関数オブジェクト
};
があったとして、
int main()
{
Function function;
Hoge hoge(function); //いったん作ってから渡す
Hoge hoge2(func); //関数を渡す
hoge.DoSomething();
hoge2.DoSomething();
}
は動きました。しかし、
int main()
{
Hoge hoge(Function()); //引数を初期化する
}
とすると次のようなエラーが出ます。
warning C4930: 'Hoge hoge(Function(__cdecl *)(void))':
プロトタイプされている関数が呼び出されませんでした (変数の定義が意図されていますか?)
また、
int main()
{
Hoge hoge(Function()); //引数を初期化する
hoge.DoSomething(); //クラスにアクセス
}
とすると次のようなほかのエラーが出ます。
error C2228: '.DoSomething' の左側はクラス、構造体、共用体でなければなりません。
しかし、例えば関数オブジェクトのコンストラクタに引数が設定されていたとして、
class Function
{
public:
Function(int dummy); //何か値を受け取る
void operator ()(); //何かしら処理する関数オブジェクト
};
となっていた時、
int main()
{
Hoge hoge(Function(1)); //引数を初期化する
hoge.DoSomething(); //クラスにアクセス
}
の呼び出しは正常にコンパイルされ、想定通りの動きをします。
全く使わなくても、一つ以上の適当な引数を何でもいいからコンストラクタが持てば、
普通にコンパイルされるみたいです。ただ、デフォルト引数を与えてHoge hoge(Function())と
同じ形ですと引数があってもできないみたいです。
まったく通らないなら最初からあきらめるですが、中途半端にちゃんと動くために
エラーの原因を知りたいと思っています。
テンプレートの場合には、引数に渡すタイミングで初期化はしてはいけないのでしょうか?
No.2ベストアンサー
- 回答日時:
蛇足っぽいけどちょっと補足:
「衝突」ってのは日本語として変でしたね. C++ の規格では
定義とも宣言とも取れるものはすべて宣言と解釈する
となっていて, 今の場合この仕様が適用されています. 実際, メッセージでも
「プロトタイプされている関数が呼び出されませんでした (変数の定義が意図されていますか?)」
と書いてありますよね. これは, 「ひょっとすると変数を定義しようとしているのかもしれないけど, (C++ の規格に従って) 関数のプロトタイプ宣言と解釈しましたよ」ってことも意味します.
Hoge hoge(Function());
のどこが「関数の宣言」なのかと疑問に思うかもしれませんが, これは実は
Hoge hoge(Function (*foo)());
と同じ意味になります. 関数の引数においては「関数」と「関数へのポインタ」が同一視されること, また「引数の名前は書かなくていい」ことに注意してください.
どう見ても宣言ととれない場合, たとえば
Hoge hoge(Function(1));
や
Hoge hoge(function);
では「変数の定義」と解釈されています.
ということで,
Hoge hoge = Hoge(Function());
のように定義することになります.
>定義とも宣言とも取れるものはすべて宣言と解釈する
なるほどそういうことですか。素早く的確な解答ありがとうございました。
大変わかりやすかったです。
Hoge hoge = Hoge(Function());
と書くことで、期待通りの動作をしました。
ただこちらはコピーコンストラクタが呼ばれるようで、
コピー禁止している場合にはできないようですね。
No.1
- 回答日時:
テンプレートは関係ありません.
・コンストラクタに Function() を渡す Hoge型の変数 hoge の定義
と
・「引数をとらないで Function を返す関数 (へのポインタ)」を引数として Hoge を返す関数 hoge の宣言
が衝突しているため後者をとっています.
C++ の規格を確認してください.
お探しのQ&Aが見つからない時は、教えて!gooで質問しましょう!
似たような質問が見つかりました
- C言語・C++・C# Cのオブジェクトファイルの逆アセンブル 5 2023/05/13 01:51
- C言語・C++・C# プログラミングのペーパーテスト 実行結果を表示せよ #include <stdio.h> int h 1 2022/07/09 15:27
- C言語・C++・C# C言語初心者 ポインタについて、お助けください、、 2 2023/03/15 23:50
- C言語・C++・C# プログラミングのペーパーテスト 実行結果がどのように表示されるか答えよ #include <stdi 1 2022/07/09 14:27
- C言語・C++・C# C言語プログラム変更 2 2022/12/21 15:03
- Windows 10 バッチファイルの記述法とルールについてアドバイスをお願いいたします。 1 2022/04/13 10:50
- Java JavaのSingletonパターンのprivateの持つ意味が分かりません。 5 2022/06/12 10:38
- Visual Basic(VBA) VBAでの共有パスにつきまして 1 2023/03/04 17:24
- JavaScript JavaScriptで「〇以上▲まで」の書き方 1 2022/07/20 14:44
- C言語・C++・C# 10個の実数に対する降順ソート結果を出力するプログラムを作りたいのですが、以下のプログラムをどう直せ 1 2022/07/09 22:16
関連するカテゴリからQ&Aを探す
デイリーランキングこのカテゴリの人気デイリーQ&Aランキング
-
VBA コレクションに2次元配列...
-
PHPで呼び出し元の関数名の取得...
-
protectedなのにアクセスできな...
-
VB6のコンボボックスのテキスト...
-
IIS5.1で「規定のドキュメント...
-
アロー演算子について
-
PHP正規表現の難題・preg_repla...
-
デフォルトの定義済みクラスに...
-
templateクラスについて
-
PHPの名前空間インポートについて
-
PHPランダム表示
-
VB.NETからVBAマクロ(引数)を呼...
-
PHPで文字列内に指定した文字が...
-
「取得先」という表現について
-
Dosブロンプトでtabを出力したい
-
ファイル名に日付の挿入
-
wordの差し込み印刷で文字...
-
DTOとEntityの差は何ですか。
-
バッチファイルでpingの結果を...
-
【C#】DataGridViewの最大列数...
マンスリーランキングこのカテゴリの人気マンスリーQ&Aランキング
-
VBA コレクションに2次元配列...
-
エラーの理由が分りません。Pri...
-
可変変数にアロー演算子を使いたい
-
VB.NETからVBAマクロ(引数)を呼...
-
PHP、ヒアドキュメント内でのIF...
-
VB.NETSystem.Xml 要素数を得る...
-
どういうプログラムを関数化を...
-
vb作成したらでbeep音が鳴りま...
-
次のhtml・cssでspan内の文字を...
-
classの再定義エラーについて
-
既存関数の上書き
-
protectedなのにアクセスできな...
-
配列の操作時にLNK2001外部シン...
-
UNIX CP "で上書きしません"
-
PHPでの画像の形式の変換
-
PHPプログラム上で「URLを直接...
-
Let's Encryptで自動更新がされ...
-
ExcelVBAで部分一致(*)をしたい
-
VB6のコンボボックスのテキスト...
-
ASPのResponse.WriteをPHPでは...
おすすめ情報