我有一個具有共同行為的基類和具有覆寫虛函式的派生類。但如果試圖將函式指標保存為std::vector,我將得到錯誤:
ISO C 禁止獲取未限定的或的地址。
括號內的非static成員函式的地址來形成一個指向成員函式的指標。
我需要這樣的東西:
class Base
{
public:
virtual int fun1(int inp)= 0;
virtual int fun2(int inp)= 0;
int init(int inp, std: :vector<std::function<int(int)>> callbacks, int index)
{
if (index == 0)
return Callbacks[0](inp)。
else
return Callbacks[1] (inp)。
}
int run()
{
return init(5, { &fun1, & fun2 }, 0) 。
}
};
class A : public Base
{
int fun1(int inp)
{
return inp * 10;
}
int fun1(int inp)
{
return inp * 100;
}
};
class B : public Base
{
int fun1(int inp)
{
return inp * 20;
}
int fun2(int inp)
{
return inp * 200;
}
};
int main(int argc, char const* argv[])
{
auto f = new B。
int e = f->run();
return 0;
有什么方法可以做到我想要的嗎?也許我可以將一個虛擬函式系結到一個容器上?或者我可以把lambda函式設定為虛擬的嗎?當我試圖在Base類中宣告lambda函式時,當我在派生類中改變函式時,我得到了錯誤:
uj5u.com熱心網友回復:
你的代碼有幾個問題:
指向成員函式的指標與指向非成員、或靜態、或 "自由 "函式的指標不一樣。這意味著這里的型別
std::function<int(int)>是錯誤的,因為它意味著自由函式或靜態函式。對成員函式指標的呼叫與正常的函式呼叫不一樣。你需要指定你要呼叫成員函式指標的物件。自C 17以來,你也可以使用更通用的
。std::invoke來呼叫成員函式的指標。你只需要啟動一次
Callbacks(可能是在承包商中),并在以后的run中使用它。在傳遞成員函式指標時,你需要語法
&ClassName::MemberFunction,你在函式呼叫中錯過了init(5, {&fun1, &fun2}, 0);。Base需要一個定義行為的虛擬析構器,以防你在以后的某個時刻將子類存盤在Base類指標中。
以下是根據上述改動的示例代碼:
#include <functional> //std::invoke
class Base
{
//成員函式指標型別
using MemFunPtrType = int(Base::*)(int)。
///存盤成員函式的指標。
std::vector<MemFunPtrType> mMemberFunctionPts。
public:
Base() // initlize the mMemberFunctionPts once!
: mMemberFunctionPts{ { &Base::fun1, &Base::fun2 } }
{}
virtual int fun1(int inp)= 0;
virtual int fun2(int inp)= 0;
virtual ~Base() = default;
//運行時根據傳遞的索引選擇正確的成員函式!。
int run(std::size_t index)
{
if (2u == mMemberFunctionPts.size() && index == 0)
return (this->*mMemberFunctionPts[index])(5)。
//或使用std::invoke。
/// return std::invoke(mMemberFunctionPts[index], this, 5);
else
return (this->*mMemberFunctionPts[index])(5)。
}
};
看到一個(這里的實時演示)
。uj5u.com熱心網友回復:
你通過語法&Class::Member(Class::Member是成員的 "限定 "名稱)獲得一個指向成員的 "指標"。
這些只是抽象意義上的指標,并且需要相對于一個物件進行解參考。
您可以使用->*或.*運算子來完成這個操作,這取決于左側是否是一個指標。
請注意,你必須明確地使用this,如果那是相關的物件。
&Base::fun1和&Base::fun2的型別是int (Base::*)(int),它不能被轉換為std::function<int(int)>。
把它放在一起:
int init( int inp, std: :vector<int (Base::*)(int)> Callbacks, int index)
{
if (index == 0)
return (this->*Callbacks[0])(inp); //最左邊的括號是必需的。
else
return (this->*Callbacks[1])(inp)。
}
int run()
{
return init(5, {&Base::fun1, &Base::fun2}, 0) 。
}
如果你不想把回呼限制在成員中,你可以使用lambda函式,捕獲this:
int init(int inp, std: :vector<std::function<int(int))> callbacks, intindex)
{
if (index == 0)
return Callbacks[0](inp)。
else
return Callbacks[1] (inp);
}
int run()
{
return init(5,
{[this](int i) { return fun1(i); },
[](int) { return 567; }. },
0)。)
uj5u.com熱心網友回復:
@PaulMcKenzie, 謝謝。現在它可以作業了:
class Base
{
public:
std::function<int(int)> fun1;
std::function<int(int)> fun2;
int init(int inp, std: :vector<std::function<int(int)>> callbacks, int index)
{
if (index == 0)
return Callbacks[0](inp)。
else
return Callbacks[1] (inp)。
}
int run()
{
return init(5, {& fun1, & fun2}, 0) 。
}
};
class B : public Base
{
public:
B()
{
fun1 = fun1B;
fun2 = fun2B;
}
private:
std::function<int(int)> fun1B = [&](int inp)
{
return inp * 20;
};
std::function<int(int)> fun2B = [&](int inp)
{
return inp * 200;
};
};
int main(int argc。char const *argv[])
{
auto f = new B()。
int e = f->run()。
assert(e == 5*20) 。
return 0;
但是上面的例子看起來更正確。
轉載請註明出處,本文鏈接:https://www.uj5u.com/ruanti/310477.html
標籤:
