質問をすることでしか得られない、回答やアドバイスがある。

15分調べてもわからないことは、質問しよう!

新規登録して質問してみよう
ただいま回答率
85.50%
C++

C++はC言語をもとにしてつくられた最もよく使われるマルチパラダイムプログラミング言語の1つです。オブジェクト指向、ジェネリック、命令型など広く対応しており、多目的に使用されています。

Q&A

解決済

4回答

8246閲覧

子クラスの関数を親クラスで使いたい

notgoodpg

総合スコア37

C++

C++はC言語をもとにしてつくられた最もよく使われるマルチパラダイムプログラミング言語の1つです。オブジェクト指向、ジェネリック、命令型など広く対応しており、多目的に使用されています。

0グッド

0クリップ

投稿2018/02/22 06:01

編集2018/02/22 06:52

前提・実現したいこと

子クラスの関数を親クラスで使いたい。

調べてみて似たような話をかなり見かけたのですが、内容をイマイチ飲み込めなかったので質問させていただいています。
よろしくお願いいたします。

// もう少し実情に即した内容を質問のサンプルコードの後に追記しました。

発生している問題・エラーメッセージ

エラー C3867 'Child::hoge': 非標準の構文です。メンバーにポインタを作成するには '&' を使用してください

といわれたので先頭に&をつけてみると

エラー C2276 '&': 仮想関数のアドレスを取ろうとしました。

調べてみても分からないことだらけで収拾がつかずにいます。

該当のソースコード

C++

1class Parent 2{ 3private: 4 std::Function<const CString(const CString &)> m_func; 5public: 6 Parent(); 7 8 Parent(std::Function<const CString(const CString &)> func){ 9 m_func = func; 10 }; 11 12 CString Execute(){ 13 return m_func(_T("do it ")); 14 }; 15}; 16class Child : public Parent 17{ 18 Child(){ 19 Parent( this->hoge); 20 }; 21 const CString hoge( const CString &str){ 22 return str + _T(" you sould... may be can!"); 23 }; 24}; 25class CMain(){ 26 Main(){ 27 CString encourage; 28 Child cld; 29 encourage = cld.Execute(); // encourageに"do it you should be can!"が入るようにしたい 30 return; 31 }; 32};

動かないです。何をしたいのかノリだけ伝われば幸いです。

最初省いていましたが、Execute()はサブスレッドの呼び出し関数ThreadExecから呼ばれるThreadProcにあたる関数で、
基底クラスのThreadProc関数で実行されることの一部を書き換えるのが最終目的です。
よって、cld.Execute();の実行結果が書き換わるのではなく、Parentクラス内で呼ばれるExecute関数の実行結果が変わってほしいのです。
うまく伝わるか分かりませんが最終的な目的は以上です。

補足情報(FW/ツールのバージョンなど)

  • Windows7/64bit SP1
  • VisualStudio2015SP
  • VC++/MFC

気になる質問をクリップする

クリップした質問は、後からいつでもMYページで確認できます。

またクリップした質問に回答があった際、通知やメールを受け取ることができます。

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

guest

回答4

0

ベストアンサー

こんな感じじゃないでしょうか?
CStringはstd::wstringに変更しました。

c++

1#include <functional> 2#include <string> 3 4class Parent 5{ 6private: 7 std::function<const std::wstring(const std::wstring &)> m_func; 8public: 9 Parent() = default; 10 11 Parent(std::function<const std::wstring(const std::wstring &)> func) { 12 m_func = func; 13 }; 14 15 std::wstring Execute() { 16 return m_func(_T("do it ")); 17 }; 18}; 19class Child : public Parent 20{ 21public: 22 Child() 23 :Parent([this](const std::wstring & arg) { return this->hoge(arg); }) 24 { 25 26 }; 27 const std::wstring hoge(const std::wstring &str) { 28 return str + _T(" you sould... may be can!"); 29 }; 30}; 31 32int main() 33{ 34 Child cld; 35 auto encourage = cld.Execute(); 36 return 0; 37}

投稿2018/02/22 06:54

hmmm

総合スコア818

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

notgoodpg

2018/02/23 06:22

ご回答ありがとうございます。 ご提示頂いた方法で目的の動作を達成できました。ありがとうございました。
guest

0

えっと、「仮想関数を上書きする」という形では物足りないでしょうか。

C++

1class Parent{ 2public: 3 CString Execute(){ 4 return perform(_T("do it ")); 5 }; 6 // 純粋仮想関数としての宣言 7 virtual const CString perform( const CString &str) = 0; 8} 9 10class Child : public Parent 11{ 12 const CString perform( const CString &str){ 13 return str + _T(" you sould... may be can!"); 14 }; 15};

投稿2018/02/22 06:23

maisumakun

総合スコア145121

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

notgoodpg

2018/02/22 06:37

ご回答ありがとうございます。 少し物足りない・・・と思います 簡単なコードに置き換えづらかったのでやっていないのですが、手元にある実際のソースでは Execute()にあたる関数はサブスレッド呼び出しで実行するstatic UINT ThreadExec()から呼ばれるUINT ThreadProc()関数で、要はスレッドの内容の処理を差し替えるのが最終目的としています。 複雑な話をきちんと伝えられる自信が無くてこのような質問にしています。
guest

0

Visual Studio 2017 で無問題。

C++

1#include <iostream> 2#include <functional> 3#include <string> 4 5class Parent{ 6private: 7 using func_type = std::function<std::string(const std::string&)>; 8 func_type m_func; 9public: 10 11 Parent(func_type func) { 12 m_func = func; 13 } 14 15 std::string Execute(){ 16 return m_func("do it "); 17 } 18}; 19 20class Child : public Parent { 21public: 22 Child() : Parent([this](const std::string& arg) { return hoge(arg);}) {} 23 24 std::string hoge( const std::string& str) { 25 return str + " you sould... may be can!"; 26 } 27 28}; 29 30int main() { 31 Child cld; 32 std::cout << cld.Execute() << std::endl; 33}

投稿2018/02/23 04:05

episteme

総合スコア16614

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

notgoodpg

2018/02/23 06:29

ご回答ありがとうございます。 こちらもラムダ式を用いる方法ですね。こちらのほうが一般的なのでしょうか (まずstaticを指定するのが関数ポインタとして用いるための関数の定義としてはより一般的っぽいですけど・・・(自分調べ)) usingを使ってテンプレート形のエイリアス?を定義できるのははじめて知りました。
episteme

2018/02/23 08:14 編集

staticな関数あるいはメンバ関数へのポインタ使うのは伝統的(?)なこともありよく用いられますが、 lambda式の登場により次第に出番を失うのではないかと。 あとメンバ関数のcall手段として std::bindにthisを与えるのは(個人的には)bad-knowhow と認識しています。動くかもしれないが、エラーとなるコンパイラがあるみたいです。bindの定義次第なのでしょうが。
guest

0

本当にやりたいことに即していないとは思いますが、ノリで回答してみました。
CString部分は本質ではないのでstd::stringに変更しています。
参考:Using generic std::function objects with member functions in one class

C++

1#include <iostream> 2#include <functional> 3 4class Parent 5{ 6private: 7 std::function<const std::string(const std::string &)> m_func; 8public: 9 //Parent(); 10 Parent(std::function<const std::string(const std::string &)> func) { 11 m_func = func; 12 }; 13 14 std::string Execute() { 15 return m_func("do it "); 16 }; 17}; 18class Child : public Parent 19{ 20public: 21 Child():Parent( std::bind(&Child::hoge, this, std::placeholders::_1)){}; 22 const std::string hoge(const std::string &str) { 23 return str + " you sould... may be can!"; 24 }; 25}; 26 27int main() { 28 Child cld; 29 std::cout << cld.Execute() << std::endl; 30 return 0; 31}

実行結果

投稿2018/02/22 06:54

can110

総合スコア38233

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

notgoodpg

2018/02/23 06:24

ご回答ありがとうございます。 こちらの方法でも目標を満たす動作しましたが、std::Bindははじめて見たので(ラムダ式に精通しているわけでもないですが・・・)今回は先にご回答頂いた方を用いました。
guest

あなたの回答

tips

太字

斜体

打ち消し線

見出し

引用テキストの挿入

コードの挿入

リンクの挿入

リストの挿入

番号リストの挿入

表の挿入

水平線の挿入

プレビュー

15分調べてもわからないことは
teratailで質問しよう!

ただいまの回答率
85.50%

質問をまとめることで
思考を整理して素早く解決

テンプレート機能で
簡単に質問をまとめる

質問する

関連した質問