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

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

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

C言語は、1972年にAT&Tベル研究所の、デニス・リッチーが主体となって作成したプログラミング言語です。 B言語の後継言語として開発されたことからC言語と命名。そのため、表記法などはB言語やALGOLに近いとされています。 Cの拡張版であるC++言語とともに、現在世界中でもっとも普及されているプログラミング言語です。

C++

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

Arduino

Arduinoは、AVRマイコン、単純なI/O(入出力)ポートを備えた基板、C言語を元としたArduinoのプログラム言語と、それを実装した統合開発環境から構成されたシステムです。

Q&A

解決済

2回答

20713閲覧

C++でメンバ関数をクラス外の関数から呼び出す方法 on Arduino

tanisou

総合スコア13

C

C言語は、1972年にAT&Tベル研究所の、デニス・リッチーが主体となって作成したプログラミング言語です。 B言語の後継言語として開発されたことからC言語と命名。そのため、表記法などはB言語やALGOLに近いとされています。 Cの拡張版であるC++言語とともに、現在世界中でもっとも普及されているプログラミング言語です。

C++

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

Arduino

Arduinoは、AVRマイコン、単純なI/O(入出力)ポートを備えた基板、C言語を元としたArduinoのプログラム言語と、それを実装した統合開発環境から構成されたシステムです。

0グッド

0クリップ

投稿2018/02/01 03:29

ArduinoのattachInterruptにメンバー関数を割り当てる方法について質問です。
このページの回答を参考に
test_class.ino

#include "test.h" Foo foo; typedef void (*fnInterrupt)(); fnInterrupt refInterrupt; void setup(){ Serial.begin(115200); attachInterrupt(0,callMethod,RISING); } void loop(){ } //--------Foo Class-------------- void Foo::bar(){ static uint8_t a = 0; a++; } void Foo::setMethod(){ setReference(this->*bar); } //------------------------------ void setReference(void (*method)()){ refInterrupt = method; } void callMethod(){ refInterrupt(); }

test.h

#ifndef __TEST_H_ #define __TEST_H_ class Foo{ public: void bar(); void setMethod(); }; #endif

というスケッチとヘッダーを作ってみました。
リンク先の回答と違い、インスタンス名を直接指定してメンバ関数の参照を渡すのではなく、インスタンス内からインスタンス自身.bar()の参照を渡して、そのメンバ関数を呼び出す関数を割り込み関数に当てたいと考えています。

/Users/username/Documents/Arduino/test_class/test_class.ino: In member function 'void Foo::setMethod()': test_class:22: error: '((Foo*)this)->Foo::bar' cannot be used as a member pointer, since it is of type '<unresolved overloaded function type>' setReference(this->*bar); ^ test_class:22: error: 'setReference' was not declared in this scope setReference(this->*bar); ^ /Users/username/Documents/Arduino/test_class/test_class.ino: At global scope: test_class:27: error: variable or field 'setReference' declared void void setReference((*method)){ ^ test_class:27: error: 'method' was not declared in this scope void setReference((*method)){ ^ exit status 1 '((Foo*)this)->Foo::bar' cannot be used as a member pointer, since it is of type '<unresolved overloaded function type>'

しかしというエラーが発生してしまいます。
まだArduinoもCも入門レベルなので質問に問題がありましたら申し訳ありません。

この問題についてわかる方がいらっしゃいましたら、ご回答いただけると嬉しいです。
よろしくお願いいたします。

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

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

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

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

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

guest

回答2

0

Arduinoの経験は全くありませんので、もし妙な回答をしていたらすみません。


fooがグローバル変数であるなら、フレンド関数を使うのが簡単かと思います。

C++

1#ifndef MY_HEADER_INCLUDED 2#define MY_HEADER_INCLUDED 3 4class Foo { 5 friend void bar(void); 6 7private: 8 const int num_; 9 10public: 11 Foo(int num) : num_(num) {} 12}; 13 14#endif

C++

1#include <iostream> 2#include <functional> 3#include "header.hpp" 4 5Foo foo(42); 6 7void bar(void) { 8 // フレンド関数はprivateな操作/属性にアクセスできる 9 std::cout << foo.num_ << std::endl; 10} 11 12using BarFunc = std::function<void(void)>; 13BarFunc func; 14 15void setFunc(const BarFunc& func) { 16 ::func = func; 17} 18void call(void) { 19 func(); 20} 21 22int main(void) { 23 setFunc(bar); 24 call(); 25 return 0; 26}

しかし、フレンド関数は使い方を誤ると思わぬバグを誘発します。
今後プログラムが肥大するなら、fooがグローバル変数であることも含め再考した方が良いでしょう。

投稿2018/02/01 08:02

編集2018/02/01 08:03
LouiS0616

総合スコア35660

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

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

tanisou

2018/02/01 09:30

ご回答ありがとうございます、確認が遅れてしまいました。 フレンド関数という存在があるのですね! 今回私がつまずいていたのは、メンバ関数を引数にできず非メンバな関数のみを引数にとるArduinoの割り込み関数にメンバ関数を動的に割り当てたいということから質問をしてみました。 フレンド関数についてイマイチまだ理解できてないのですが、もっと調べて見て使えそうだったら検討してみたいとおもいます! ご回答ありがとうございました!
guest

0

ベストアンサー

VC++でおためし。Arduinoでも同じぢゃろ。

C++

1#include <iostream> 2 3class Operation { 4 int last_; 5public: 6 int add(int x, int y) { return last_ = x+y; } 7 int sub(int x, int y) { return last_ = x-y; } 8 int mul(int x, int y) { return last_ = x*y; } 9 int last() const { return last_; } 10}; 11 12class Foo { 13 Operation* opr_; 14 int (Operation::* fun_)(int, int); 15public: 16 void set(Operation* opr, int (Operation::* fun)(int, int) ){ 17 opr_ = opr; 18 fun_ = fun; 19 } 20 int exec(int x, int y) { 21 return (opr_->*fun_)(x, y); 22 } 23}; 24 25int main() { 26 using namespace std; 27 28 Operation op; 29 Foo foo; 30 31 foo.set(&op, &Operation::add); 32 cout << "1+2= " << foo.exec(1,2) << endl; 33 foo.set(&op, &Operation::mul); 34 cout << "2+3= " << foo.exec(2,3) << endl; 35 cout << "last result = " << op.last() << endl; 36} 37 38/* 実行結果 391+2= 3 402+3= 6 41last result = 6 42*/

[追記] こゆこと?

C++

1#include <iostream> 2 3class Operation { 4 int last_; 5public: 6 int add(int x, int y) { return last_ = x+y; } 7 int sub(int x, int y) { return last_ = x-y; } 8 int mul(int x, int y) { return last_ = x*y; } 9 int last() const { return last_; } 10}; 11 12class Foo { 13 Operation* opr_; 14public: 15 void set(Operation* opr) { 16 opr_ = opr; 17 } 18 int exec_add(int x, int y) { 19 return opr_->add(x, y); 20 } 21}; 22 23int main() { 24 using namespace std; 25 26 Operation op; 27 Foo foo; 28 29 foo.set(&op); 30 cout << "1+2= " << foo.exec_add(1,2) << endl; 31 cout << "2+3= " << foo.exec_add(2,3) << endl; 32 cout << "last result = " << op.last() << endl; 33} 34 35/* 実行結果 361+2= 3 372+3= 5 38last result = 5 39*/

投稿2018/02/01 03:51

編集2018/02/01 06:59
episteme

総合スコア16614

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

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

tanisou

2018/02/01 06:05

早速のご回答ありがとうございます! すみません、僕の質問の仕方が悪かったのと理解不足なのですが Pythonで言う所のselfをインスタンスのメソッドで他の関数へ渡し、そのインスタンスに属する何か他のメソッドを呼びたいということです。 それともCやC++ではメンバ関数の引数で前もって特定のクラスやメソッド、またそのポインタとして宣言していないと使えないということでしょうか。 関数名、変数名など異なりますが、Pythonでこんな感じのことをCで行いたかったのです。 instance_reference = None def set_instance(instance): global instance_reference instance_reference = instance def call_method(): instance_reference.add() class Test(): def __init__(self): super(Test,self).__init__() self.set_self() def add(self): print('called instance_reference.add !') def set_self(self): set_instance(self) if __name__ == '__main__': Instance_test = Test() call_method()
episteme

2018/02/01 06:59

追記した。これがお望みのものだろうか。
tanisou

2018/02/01 09:24

ありがとうございます!!! おかげさまで詰まっていたところを解決することができました。
guest

あなたの回答

tips

太字

斜体

打ち消し線

見出し

引用テキストの挿入

コードの挿入

リンクの挿入

リストの挿入

番号リストの挿入

表の挿入

水平線の挿入

プレビュー

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

ただいまの回答率
85.48%

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

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

質問する

関連した質問