如何在模板成员中引用派生类?
How to refer derived class in template member?
下面的代码无法编译:
struct Base
{
std::vector<void(Base::*)(void)> x;
};
struct Derived : public Base
{
void foo() {}
};
// ...
Derived d;
d.x.push_back(&Derived::foo);
是否可以在模板成员x
中引用派生类?在上面的例子中,我准确地指定了Base
,派生类不能将自己的成员函数推送到向量x
。
强制转换是不好的,因为您的代码必须假设它只会针对Derived
类的实例调用。这意味着您要么必须假设x
中的所有项目都是Derived
的实例(在这种情况下,x
声明是通用的,应该更改为std::vector<void(Derived::*)(void)> x;
(,或者您必须维护额外的信息,哪个类方法存储在x
的特定位置。这两种方法都很糟糕。
在现代C++最好这样做:
struct Base
{
std::vector<std::function<void()>> x;
};
struct Derived : public Base
{
void foo() {}
};
// ...
Derived d;
d.x.push_back([&d](){ d.foo(); });
另一个好方法是 CRTP:
template<class T>
struct Base
{
std::vector<void(T::*)(void)> x;
};
struct Derived : public Base<Derived>
{
void foo() {}
};
// ...
Derived d;
d.x.push_back(&Derived::foo);
可以,但没有隐式转换; 它需要强制转换。
Derived d;
d.x.push_back(static_cast<void(Base::*)()>(&Derived::foo));
需要注意的是,如果您将该指针指向成员与不是真正Derived
的对象一起使用,则行为是未定义的。小心。
作为附录,如果你想在获取指针时摆脱强制转换,你可以通过封装推送(使用一些静态类型检查来启动(:
struct Base
{
std::vector<void(Base::*)(void)> x;
template<class D>
auto push_member(void (D::* p)()) ->
std::enable_if_t<std::is_base_of<Base, D>::value> {
x.push_back(static_cast<void(Base::*)()>(p));
}
};
我想我会通过调用基上的非虚拟成员函数来表达这一点。
例:
#include <vector>
struct Base
{
std::vector<void(Base::*)(void)> x;
// public non-virtual interface
void perform_foo()
{
foo();
}
private:
// private virtual interface for the implementation
virtual void foo() = 0;
};
struct Derived : public Base
{
private:
// override private virtual interface
void foo() override {}
};
// ...
int main()
{
Derived d;
d.x.push_back(&Base::perform_foo);
auto call_them = [](Base& b)
{
for (auto&& item : b.x)
{
(b.*item)();
}
};
call_them(d);
}
相关文章:
- 如何使用基类指针引用派生类成员
- 如何引用基类的派生类?
- 通过基类接受方法转发派生 UniquePtr 的右值会移动引用而不是复制
- 如何复制只引用基类的派生类
- 从 Base 引用对象调用派生类的成员
- C++ 为什么要将对基类的引用传递给派生类的构造函数
- 通过基类引用派生类后打印的错误值
- 如何在 c++ 中通过基类引用访问派生类的对象?
- 从基类的共享指针向下转换到派生类的引用
- 如何在模板成员中引用派生类?
- 传递指针或引用派生类,以便调用基类方法
- 通过引用派生类对象从基类对象执行向下转换时引发bad_cast异常
- 不能引用派生模板类中的基类成员
- 是否可以将常量unique_ptr引用(派生类)转换为shared_ptr(基类)
- 通过引用派生的来调用C++基实现
- 从c++中另一个(不相关的!)类的基类引用派生类的对象
- 从基类引用派生类参数
- 引用派生类中的基类成员
- 如何在指向基类对象的指针向量中引用派生对象
- C++ - 基类指针,方法指针,引用派生类,方法