2013-02-28 16 views
10

よしであるクラス内の関数ポインタのベクトルから関数を呼び出して、私のメインの中で私が持っているC++、関数定義がメイン

class SomeClass() 
{ 
    public: 
     void addThingy(void (*function)()); 
     void actionWithDiffrentOutcomes(); 
    private: 
     std::vector<void (**)()> vectoroffunctions; 
} 
SomeClass::addThingy(void (*function)()) 
{ 
    vectoroffunctions.push_back(&function); 
} 
SomeClass::actionWithDiffrentOutcomes() 
{ 
    (*vectoroffunctions[0])();; 
} 

私はポインターへの新しいアイディアの一種ですが、私のC++の本を読んで、グーグルでエクステンションしました。これは正しく、コンパイル、実行されますが、私は "actionWithDiffrentOutcomes()"と呼び出すとき、私はアクセス違反を取得します。私は何をすべきか分からない。それは正しいようですが、何かが明らかに間違っています。では、定義が別のクラスにあるときにクラス内から関数を呼び出すにはどうすればよいですか?

私はすべてのオプションをswitch文にハードコードすることができないので、このようにしています。

+0

サンプルコードはコンパイルされません。構文を2回確認して質問を編集してください。 – congusbongus

+0

このコードはコンパイルされません。 [短い、自己完結型、正しい(コンパイル可能)、例](http://sscce.org/)をご提供ください。 – Johnsyweb

答えて

12

あなたのコードはほぼ正しいです。あなたのベクトルは、単に関数へのポインタではなく、関数へのポインタへのポインタを誤って保持しています。 addThingyvectorfunctionポインタのアドレスを追加していますが、そのポインタは次の行の範囲外になります。

//Store pointers to functions, rather than 
//pointers to pointers to functions 
std::vector<void (*)()> vectoroffunctions; 

SomeClass::addThingy(void (*function)()) 
{ 
    //Don't take the address of the address: 
    vectoroffunctions.push_back(function); 
} 

はまた、あなたもコンパイルからコードを停止する必要があり、コードの残りの部分で構文エラーがたくさんある:次のように

はあなたのコードを変更し

+0

ああ、ありがとう、それは理にかなっている。また、構文についてごめんね、私はそれをnp ++にコピーして、私のプログラム全体を投稿するのではなく、ここに投稿しました。 –

5

問題はここにある:

vectoroffunctions.push_back(&function); 

あなたはローカル変数のアドレスを追加しています。ローカル変数は、関数から戻ると破棄されます。ベクトルが格納されているアドレスは、実行時に"アクセス違反"エラーを発生させる理由で、破棄されたオブジェクトを指しています。

この問題を修正するには、次の操作を行います。

最初の変更、これにこの

std::vector<void (**)()> vectoroffunctions; 

:今すぐやる

std::vector<void()> _functions; //vector of function-type 

:と実質的に同じである

std::vector<void (*)()> _functions; //vector of function-pointer-type 
            //I changed the name also! 

this:

_functions.push_back(function); //add copy! 

それをより柔軟にするために、あなたはようstd::functionと一緒にテンプレートを使用することができます。今、あなたは機能だけでなく、ファンクタを格納するためにそれを使用することができます

class A 
{ 
    public: 
     template<typename Function> 
     void add(Function && fn) 
     { 
      _functions.push_back(std::forward<Function>(fn)); 
     } 
     void invoke_all() 
     { 
      for(auto && fn : _functions) 
       fn(); 
     } 
    private: 
     std::vector<std::function<void()>> _functions; 
}; 

void myfunction() { std::cout << "myfunction" << std::endl ; } 

struct myfunctor 
{ 
     void operator()() { std::cout << "myfunctor" << std::endl ; } 
}; 

A a; 
a.add(myfunction); //add function 
a.add(myfunctor()); //add functor! 
a.invoke_all(); 

出力(Online Demo):

myfunction 
myfunctor 

希望します。

+0

可変引数を持つ関数のための優雅なソリューション? –

+0

@sid:ユースケースとは何ですか? – Nawaz

1

関数ポインタがはるかに読みやすいtypedefsと、次のとおりです。

typedef void (*RequiredFunction)(); 

その後、あなたはこのようなaddThingy()宣言することができますので、同様

void addThingy(RequiredFunction function); 

そしてvectoroffunctions

std::vector<RequiredFunction> vectoroffunctions; 

の定義をaddThingyは:

void SomeClass::addThingy(RequiredFunction function) 
{ 
    vectoroffunctions.push_back(function); 
} 

そして、あなたのmain()がより多くのようになります。*秒と間違いを犯すすると&

int main() 
{ 
    SomeClass sc; 
    RequiredFunction pointerfunc = somefunction; 
    sc.addThingy(pointerfunc); 
    sc.actionWithDiffrentOutcomes(); 
} 

ははるかに少ないです!

関連する問題