在 Array/Vector 容器中存储虚函数
Storing virual functions in Array/Vector container
我有一个具有共同行为的基础 class 和具有覆盖虚函数的派生 class。但是如果试图将函数指针保存为 std::vector
我会得到错误:
ISO C++ forbids taking the address of an unqualified or
parenthesized non-static member function to form a pointer to member function.
我需要这样的东西:
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
class 中声明 lambda 函数时,当我在派生 class 中更改函数时,出现错误:
您将获得一个指向成员的“指针”,语法为 &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); // The leftmost parentheses are necessary.
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, int index)
{
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);
}
@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;
}
但是上面的例子看起来更正确。
您的代码有几个问题:
指向成员函数的指针与指向非成员、静态或“自由”函数的指针不同。这意味着这里的类型 std::function<int(int)>
是错误的,因为它意味着自由函数或静态函数。
成员函数指针的调用和普通的函数调用不一样。你需要 specify the object to which you are calling the member function pointer. Since C++17 you can also invoke the pointer to member function using more generic std::invoke
.
你只需要初始化Callbacks
一次(可能在contractor中),然后在run
中使用它。
传递成员函数指针时,您需要语法 &ClassName::MemberFunction
,您在函数调用 init(5, {&fun1, &fun2}, 0);
.
中遗漏了它
Base
需要一个 virtual destructor for defined behavior,以防您稍后将子项存储在 Base
class 指针中。
以下是根据上述更改的示例代码:
#include <functional> // std::invoke
class Base
{
// member function pointer type
using MemFunPtrType = int(Base::*)(int);
// to store the member functions pointers
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;
// run choose the correct member function as per the passed index!
int run(std::size_t index)
{
if (2u == mMemberFunctionPts.size() && index == 0)
return (this->*mMemberFunctionPts[index])(5);
// or using std::invoke
// return std::invoke(mMemberFunctionPts[index], this, 5);
else
return (this->*mMemberFunctionPts[index])(5);
}
};
看到一个(Live Demo Here)
我有一个具有共同行为的基础 class 和具有覆盖虚函数的派生 class。但是如果试图将函数指针保存为 std::vector
我会得到错误:
ISO C++ forbids taking the address of an unqualified or
parenthesized non-static member function to form a pointer to member function.
我需要这样的东西:
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
class 中声明 lambda 函数时,当我在派生 class 中更改函数时,出现错误:
您将获得一个指向成员的“指针”,语法为 &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); // The leftmost parentheses are necessary.
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, int index)
{
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);
}
@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;
}
但是上面的例子看起来更正确。
您的代码有几个问题:
指向成员函数的指针与指向非成员、静态或“自由”函数的指针不同。这意味着这里的类型
std::function<int(int)>
是错误的,因为它意味着自由函数或静态函数。成员函数指针的调用和普通的函数调用不一样。你需要 specify the object to which you are calling the member function pointer. Since C++17 you can also invoke the pointer to member function using more generic
std::invoke
.你只需要初始化
Callbacks
一次(可能在contractor中),然后在run
中使用它。传递成员函数指针时,您需要语法
中遗漏了它&ClassName::MemberFunction
,您在函数调用init(5, {&fun1, &fun2}, 0);
.Base
需要一个 virtual destructor for defined behavior,以防您稍后将子项存储在Base
class 指针中。
以下是根据上述更改的示例代码:
#include <functional> // std::invoke
class Base
{
// member function pointer type
using MemFunPtrType = int(Base::*)(int);
// to store the member functions pointers
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;
// run choose the correct member function as per the passed index!
int run(std::size_t index)
{
if (2u == mMemberFunctionPts.size() && index == 0)
return (this->*mMemberFunctionPts[index])(5);
// or using std::invoke
// return std::invoke(mMemberFunctionPts[index], this, 5);
else
return (this->*mMemberFunctionPts[index])(5);
}
};
看到一个(Live Demo Here)