さて、私のメインでは:
void somefunction();
int main()
{
//bla bla bla
SomeClass myclass = SomeClass();
void(*pointerfunc)() = somefunction;
myclass.addThingy(pointerfunc);
//then later i do
myclass.actionWithDiffrentOutcomes();
}
void somefunction()
{
//some code
}
クラスで:
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 ++の本、グーグル、extを読みました。これは正しいように見え、コンパイル、実行されますが、「actionWithDiffrentOutcomes()」を呼び出すと、アクセス違反が発生します。どうすればいいかわかりません。それは正しいようですが、何かが明らかに間違っています。それで、定義が別の中にあるときに、クラス内から関数を呼び出すにはどうすればよいですか?
私はすべてのオプションをswitchステートメントにハードコーディングできないので、このようにしています。
あなたのコードはほぼ正しいです。あなたのベクトルは、単に関数へのポインターではなく、誤って関数へのポインターへのポインターを保持しています。 addThingy
はfunction
ポインターのアドレスをvector
に追加していますが、そのポインターは次の行でスコープ外になります。
次のようにコードを変更します。
//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);
}
また、残りのコードには多くの構文エラーがあり、コードのコンパイルを停止する必要があります。
問題はここにあります:
vectoroffunctions.Push_back(&function);
local変数のアドレスを追加しています。関数から戻ると、ローカル変数は破棄されます。ベクトルが格納するアドレスは破棄されたオブジェクトを指しているため、実行時に「アクセス違反」エラーが発生します。
これを修正するには、次のようにします。
まずこれを変える
std::vector<void (**)()> vectoroffunctions;
これに:
std::vector<void (*)()> _functions; //vector of function-pointer-type
//I changed the name also!
これは実質的に以下と同じです:
std::vector<void()> _functions; //vector of function-type
今これを行います:
_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();
出力( オンラインデモ ):
myfunction
myfunctor
お役に立てば幸いです。
関数ポインタは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();
}
_
間違いを犯す_*
_ sと_&
_ sがはるかに少ない!