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

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

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

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

Q&A

解決済

5回答

1403閲覧

c++ クラスのメンバの関数ポインターに関数のアドレスを入れる方法

退会済みユーザー

退会済みユーザー

総合スコア0

C++

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

0グッド

2クリップ

投稿2019/04/03 10:57

編集2019/04/06 04:23

クラスのメンバ変数として関数ポインターを用意してそこにそのクラスの関数のポインターを入れたりクラスの外の関数のポインターを設定する方法が知りたいです。void(*scp)();// にsample::cfを設定する方法が知りたいのですが教えてくれますでしょうか?

C++

1#include <iostream> 2#include "conio.h" 3#include <math.h> 4using namespace std; 5 6 7 8 9void f() 10{ 11 printf("関数ポインター"); 12} 13 14int add(int a, int b) 15{ 16 return a + b; 17} 18 19class sample 20{ 21public: 22 23 int cx; 24 void cf() 25 { 26 printf("関数ポインター"); 27 } 28 29 int c_add(int a, int b) 30 { 31 return a + b; 32 } 33 34 void(*scp)();// 35}; 36 37int main() 38{ 39 sample sa,sa2; 40 sample *sp = new sample(); 41 42 void(*fp)() = f; 43 int(*fp2)(int a, int b) = add; 44 //(*fp)(); 45 int x = (*fp2)(2,3); 46 //printf("%d",x); 47 48 void (sample::*cfp)() = &sample::cf; 49 //(sa.*cfp)(); 50 //(sa2.*cfp)(); 51 //(sp->*cfp)(); 52 53 int sample::*cp; 54 cp = &sample::cx; 55 56 57 58 59 60 _getch(); 61 return 0; 62} 63

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

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

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

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

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

cateye

2019/04/03 11:43 編集

前の質問でも言いましたが、VC固有の関数等(scanf_s(),_getch())使わないでほしいです。LinuxのC(gcc,clang)ではコンパイルできません。
退会済みユーザー

退会済みユーザー

2019/04/03 11:46

わかりました。
cateye

2019/04/03 11:50

ちなみに、2回めのscanf()ちゃんと動きますか?
退会済みユーザー

退会済みユーザー

2019/04/03 12:03

僕のWindows10 visual studio でエラーになりscanf_sを使ってくださいってなるのでそうしてたんですけど指摘があったので編集しました。
cateye

2019/04/03 13:47

scanf()自体は仕様を把握していないと使い方が難しい関数です。まぁ、数値の入力は問題ないのですが文字列を入力する時は問題が発生する可能性があります。VCのエラーは"_CRT_SECURE_NO_WARNINGS"を設定すれば出なくなります。 で、本題ですが「結局何がしたいのでしょう?」 ソースを見ても何が作りたいのか分かりません。勉強のためということならいいのですが・・・
退会済みユーザー

退会済みユーザー

2019/04/04 03:36 編集

usingとtypdefの仕様の違いが知りたいです。
退会済みユーザー

退会済みユーザー

2019/04/04 03:36

特に何か作ってるわけではないのですが忘れたので動作を確認しています 戻り値があり仮引数のある関数ポインターを返す関数の書き方が知りたいのですが using やtypdefを使わずそのまま書く方法を教えてくれますか?
cateye

2019/04/04 04:18 編集

追記しました。 ・・・できれば自分で解決してほしかった。
cateye

2019/04/04 06:48 編集

>理解に困っています 理解が出来ない・・・は、頭がついていってない証拠です、まず理解しましょう。 C++の言語仕様確かめましたか? コンパイルして動かしてみれば? どのような言語でもコンパイルして動かせば異常がわかります。 デバッグ70%ですよd^^ 手前味噌ですが「10日間でプログラムを作ろうと思ったら。」 https://xcateye.blogspot.com/2019/03/blog-post.html
yominet

2019/04/04 15:04

質問変わってませんか?
退会済みユーザー

退会済みユーザー

2019/04/06 04:55

回答している人が分の獲たい回答と違うのでタイトルと文章を編集しました。
guest

回答5

0

ありません。というのが回答になります。

というのも(非staticな)メンバ関数と、非メンバ関数は違うものだからです。
(非staticな)メンバ関数は呼び出し時にthisポインタを必要としています。
非メンバ関数にはそれがありません。

どうしてもというのならば、staticメンバ関数(静的メンバ関数)を用いるかラムダ式によるクロージャーを用いることになります。


メンバ変数・関数を使わないのでthisポインタがいらない というのならば
静的メンバ関数を用いる事になります。

c++

1#include<iostream> 2using namespace std; 3 4class Sample{ 5public: 6 static int calc(int a, int b){ return a * b; } 7 int (*func)(int, int) = calc; 8}; 9 10int add(int a, int b){ return a + b; } 11 12int main(){ 13 Sample s; 14 cout << s.func(100, 100) << endl; 15 16 s.func = add; 17 cout << s.func(100, 100) << endl; 18 19 // もどしてみる 20 s.func = Sample::calc; // s.calcでも可能 21 cout << s.func(100, 100) << endl; 22}

thisポインタが必要という場合は

  • どこかにthisポインタ or nullptrを保存しておいてint add(int a, int b, void* _this)みたいな感じに渡す。
  • ラムダ式(もしくは関数オブジェクト)によるクロージャーを用いる

どちらかしか方法はないでしょう。

投稿2019/04/08 08:53

asm

総合スコア15147

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

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

退会済みユーザー

退会済みユーザー

2019/04/08 09:09

質問ですがクラス内でこのようなコードがコンパイルエラーにならないのですが これをメイン関数部で使うことはできずやってはいけないコードなのでしょうか? void (sample::*aa)() = &sample::c_f; int (sample::*bb)(int,int) = &sample::c_add;
asm

2019/04/08 11:13

それはメンバ関数のポインタなので、呼び出しの際にインスタンス(thisポインタ)を指定する必要があります。 また、非メンバ関数を代入することもできません。 そのことを認識しているのならば、クラス外で使っても問題ありません。
退会済みユーザー

退会済みユーザー

2019/04/08 11:20

再度質問ですが、Main関数部で使うコードの書き方がわからず色々試しのですがコンパイルエラーになってしますMain関数で使うコードの例を教えてくれますでしょうか?
episteme

2019/04/08 11:44

答えておいたぞー
asm

2019/04/08 11:51

class Sample{ public: void cf(){ cout << "member function" << endl; } void (Sample:: *aaa)() = &Sample::cf; }; int main(){ Sample s; (s.*(s.aaa))(); } こういう事でしょうか? 結局メンバ関数以外を入れることはできないので > そのクラスの関数のポインターを入れたりクラスの外の関数のポインターを設定する方法 には成り得ませんが
退会済みユーザー

退会済みユーザー

2019/04/08 15:15

クラスの関数ポインターですが 同じクラスの場合はどのインスタンスの変数でも関数ポインターを使うことができるみたいですがそいう理解でいいのでしょうか?
episteme

2019/04/08 19:38

それでいいんじゃない?
asm

2019/04/08 21:59

メンバーポインタは&Sample::cfには、どのインスタンスのメンバーか?って情報がありません。 クラス内でcfは、この位置って情報のみです。 それは情報を置く場所がメンバ変数だろうがローカル変数だろうが変わりません。 よって Sample a,b; (a.*(b.aaa))(); は正しいです。
guest

0

こーゆーことがやりたいのかな?

C++

1#include <iostream> 2#include <functional> 3 4void f() { 5 printf("フツー の関数ポインター\n"); 6} 7 8class sample { 9 const char* name; 10public: 11 sample(const char* n) : name(n), 12 scp([this]() { cf();}) // ここでセット 13 {} 14 void cf() { printf("%s の関数ポインター\n", name); } 15 std::function<void()> scp;// 16}; 17 18int main() { 19 sample s("hoge"); 20 std::function<void()> t; 21 t = f; 22 t(); 23 t = s.scp; 24 t(); 25 return 0; 26}

投稿2019/04/06 05:41

編集2019/04/06 05:47
episteme

総合スコア16614

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

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

退会済みユーザー

退会済みユーザー

2019/04/07 13:53

質問ですが//ここでセット こコード部でエラーになってしまいます。 環境はwindows10 visual studio
episteme

2019/04/07 20:51

どんなエラー? コンパイラのバージョンは?
退会済みユーザー

退会済みユーザー

2019/04/08 08:10

手で書き写していたので自分の間違えでしたすいません。
退会済みユーザー

退会済みユーザー

2019/04/08 08:12

質問ですがもしこのようなコードがクラス内にあったとしたらどうやってメイン関数部で利用すればいいのですか? void (sample::*aa)() = &sample::c_f; int (sample::*bb)(int,int) = &sample::c_add;
episteme

2019/04/08 11:09

#include <cstdio> class sample { public: void c_f() { printf("関数ポインター"); } int c_add(int a, int b) { return a + b; } }; int main() { sample s; void (sample:: * aa)() = &sample::c_f; (s.*aa)(); int (sample:: * bb)(int, int) = &sample::c_add; printf("%d", (s.*bb)(1,2)); }
episteme

2019/04/08 12:02

#include <cstdio> class sample { public: void c_f() { printf("関数ポインター"); } int c_add(int a, int b) { return a + b; } void (sample::* aa)(); int (sample::* bb)(int, int); sample() : aa(&sample::c_f), bb(&sample::c_add) {} }; int main() { sample s; (s.*s.aa)(); printf("%d", (s.*s.bb)(1,2)); }
episteme

2019/04/08 12:08

...で、何がしたいん?
退会済みユーザー

退会済みユーザー

2019/04/08 14:29

自分は初学者のため関数ポインタを使った処理の使い方一覧みたいなサンプルコードが欲しいので いろいろ試してました。
guest

0

ベストアンサー

元コードもなにも見ないで。

void func(void)
{
// なんやかや
}

// 関数ポインタを戻り値にする関数
void(*)(void) retfunc(void)
{
return func;
}

投稿2019/04/03 12:43

y_waiwai

総合スコア87719

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

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

0

答えなのかどうなのか・・・

c++

1#include <iostream> 2// 3using namespace std; 4 5using FUNC_VO = void (*)(); 6using FUNC_IN = int (*)(int, int); 7 8class test 9{ 10 public: 11 int add(int a, int b) { return a + b; } 12 13 void f(); 14 15 void (*fx)(); 16}; 17 18void test::f() 19{ 20 int (test::*fp)(int a, int b) = &test::add; 21 int x = (this->*fp)(1, 2); 22 printf("%d\n", x); 23} 24 25static void f(void) 26{ 27 printf("関数ポインタ\n"); 28} 29 30static FUNC_VO f2(FUNC_IN fp) 31{ 32 int a; 33 int b; 34 scanf("%d", &a); 35 scanf("%d", &b); 36 37 printf("%d\n", (*fp)(a, b)); 38 // return void (*px)() = f; 39 return f; 40} 41 42static int adds(int a, int b) 43{ 44 return a + b; 45} 46 47int main() 48{ 49 // f2(adds); 50 51 // void (*x)() = f2(adds); 52 FUNC_VO sample = f2(adds); 53 (*sample)(); 54 55 return 0; 56} 57 58 59

結果

text

1usr ~/Project/test/teratail % c++ t182725.cpp 2usr ~/Project/test/teratail % ./a.out 32 43 55 6関数ポインタ 7usr ~/Project/test/teratail %

c++

1#include <iostream> 2// 3using namespace std; 4 5//using FUNC_VO = void (*)(); 6// using FUNC_IN = int (*)(int, int); 7 8class test 9{ 10 public: 11 int add(int a, int b) { return a + b; } 12 13 void f(); 14 15 void (*fx)(); 16}; 17 18void test::f() 19{ 20 int (test::*fp)(int a, int b) = &test::add; 21 int x = (this->*fp)(1, 2); 22 printf("%d\n", x); 23} 24 25static void f(void) 26{ 27 printf("関数ポインタ\n"); 28} 29 30static void (*f2(int (*fp)(int, int)))() 31{ 32 int a; 33 int b; 34 scanf("%d", &a); 35 scanf("%d", &b); 36 37 printf("%d\n", (*fp)(a, b)); 38 // 39 return f; 40} 41 42static int adds(int a, int b) 43{ 44 return a + b; 45} 46 47int main() 48{ 49 void (*sample)() = f2(adds); 50 (*sample)(); 51 52 return 0; 53} 54

「追記」
コンストラクタで初期化するというのは↓のような事ですが?

c++

1usr ~/Project/test/teratail % c++ test.cpp 2usr ~/Project/test/teratail % ./a.out 37 43 5usr ~/Project/test/teratail % cat test.cpp 6#include <iostream> 7 8// function prototype 9int sub(int a, int b); 10int add(int a, int b); 11 12class Test 13{ 14 15 int (*func)(int, int); 16 17 public: 18 Test(int (*f)(int, int)) : func(f) {} 19 int exec(int a, int b) { return (*func)(a, b); } 20}; 21 22int add(int a, int b) 23{ 24 return a + b; 25} 26 27int sub(int a, int b) 28{ 29 return a - b; 30} 31 32int main(void) 33{ 34 Test ta(add); 35 Test ts(sub); 36 37 std::cout << ta.exec(5, 2) << std::endl; 38 std::cout << ts.exec(5, 2) << std::endl; 39 40 return 0; 41} 42usr ~/Project/test/teratail %

投稿2019/04/03 12:33

編集2019/04/08 10:02
cateye

総合スコア6851

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

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

cateye

2019/04/03 12:35

ワーニングは出ます。 t182725.cpp:26:6: warning: no previous prototype for function 'f' [-Wmissing-prototypes] void f(void) ^ t182725.cpp:31:9: warning: no previous prototype for function 'f2' [-Wmissing-prototypes] FUNC_PS f2(FUNC_IN fp) ^ t182725.cpp:49:5: warning: no previous prototype for function 'adds' [-Wmissing-prototypes] int adds(int a, int b) ^ t182725.cpp:65:13: warning: unused variable 'sample' [-Wunused-variable] FUNC_PS sample = f2(adds); ^ 4 warnings generated.
cateye

2019/04/03 12:57 編集

こちらの環境 Linux usr.Mint191 4.18.0-17-generic clang version 9.0.0 (trunk 354955) コンパイラオプション:clang++ -Wno-c++98-compat -Wno-padded -pipe -std=c++17 -Weverything -Ofast
cateye

2019/04/04 03:38

上記ワーニングは、関数をstaticにすることで出なくなります。 修正済みのソース上げておきます。
cateye

2019/04/04 07:50 編集

void (*f2(int (*fp)(int, int)))() 分解します・・・ちょっと怪しいけどw ①int (*fp)(int, int)・・・2つのintをパラメータとしてintを返す関数のポインタ ②void (*f2(①))()・・・①をパラメータとして持つf2という関数 ③void (*)()・・・voidを返す関数へのポインタ
退会済みユーザー

退会済みユーザー

2019/04/07 13:59

質問ですがtestクラスのfx関数ポインターにadd関数のポインターを入れたいのですがどうすればいいのでしょうか?(add関数の型がfxと同じだと仮定して) サンプルを見るとf関数でポインターを設定していますが 関数ポインターの宣言時に設定する方法を知りたいです。
cateye

2019/04/07 20:19

コンストラクタで初期化するとか・・・考えられますが、いまテストしている時間がないです。考えてやってみましょう。
退会済みユーザー

退会済みユーザー

2019/04/08 05:03

コンストラクタで設定することはできますが 僕が提示したコードのsample::scp にsample::cf を設定することはそもそもできないのでしょうか? 試しましたができません イメージは[ void (*scp)() = cf; ]なのですがエラーになります。ようするにこのやりかたは"できない" という結論でよろしいのでしょうか?
cateye

2019/04/08 10:05

とりあえずテストコード上げときます。 結局何がしたいのか分かりません?・・・「忘れている」とおっしゃいましたが“忘れている”レベルではないと思います。
guest

0

アナタが求めているのはこんなの?

C++

1#include <iostream> 2 3int f() { 4 std::cout << "f() called" << std::endl; 5 return 123; 6} 7 8typedef int(*xx)(); 9 10xx t() { 11 return &f; // 関数ポインタを返す 12} 13 14int main() { 15 int(*sample)() = t(); 16 std::cout << sample(); // (間接的にf()を呼ぶ 17 return 0; 18}

投稿2019/04/03 12:14

episteme

総合スコア16614

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

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

あなたの回答

tips

太字

斜体

打ち消し線

見出し

引用テキストの挿入

コードの挿入

リンクの挿入

リストの挿入

番号リストの挿入

表の挿入

水平線の挿入

プレビュー

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

ただいまの回答率
85.50%

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

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

質問する

関連した質問