c++ - C++ 函数指针参数和类继承自动转换
问题描述
首先抱歉,如果问题的名称不够清楚。我真的不知道如何称呼这个问题。
所以我在一个类中有一个函数指针,它像一个 java 回调一样工作,我用一些参数调用它,比如它本身是从父类派生的,就像在这个例子中一样:
class Parent;
using f_Call = void(*)(Parent*);
class Parent
{
public:
void setCallback(f_Call call)
{
mOnCall = call;
}
protected:
f_Call mOnCall = nullptr;
};
class Child1 : Parent
{
public:
void doSomething()
{
// some work..
if (mOnCall)
mOnCall(this);
}
};
void onCallExe(Parent* p)
{
Child1* child = (Child1*)p;
// do some more work...
}
int main()
{
Child1 child;
child.setCallback(onCallExe);
child.doSomething();
}
我的问题是,C++ 是否有办法在 onCallExe 中自动进行从父级到子级的强制转换,所以我不必为我调用的每个函数都这样做。
谢谢!
解决方案
奇怪地重复出现的模板模式可能是一种选择。但是,您将为每个派生类创建单独的基类,因此您不能多态地使用它们——除非您提供一个单独的公共基类。如果循环模板函数覆盖了基础中的虚拟函数,您可能最终会到达您想要获得的位置:
struct Base
{
virtual ~Base() { }
virtual void f() = 0;
};
template <typename T>
struct Intermediate : Base
{
void f() override
{
if(callback)
callback(static_cast<T*>(this));
}
void setCallback(void(*c)(T*))
{
callback = c;
}
private:
void(*callback)(T*) = nullptr;
};
struct Derived : Intermediate<Derived>
{
};
void g(Derived*) { }
void demo()
{
Derived d;
d.setCallback(g);
d.f();
}
(如果你不需要多态,你可以跳过Base
类——那么f
也不必是虚拟的。)
仅当您想通过指针或引用设置回调时Base
,您会遇到一些麻烦,因为您不能拥有虚拟模板成员函数。您可以提供一个独立的辅助函数:
template <typename T>
void setCallback(Base& b, void(*callback)(T*))
{
dynamic_cast<Intermediate<T>&>(b).setCallback(callback);
}
动态转换将抛出一个std::bad_cast
if b
is of in proper type - 不幸的是,这是一个相当昂贵的运行时事情,让编译器确定指向/引用的对象是否(通常)是正确类型的安全方法是不可能的。
推荐阅读
- java - 如何创建具有泛型类型的bean?
- java - int 自动将其值设置为特定数字,而我不打算这样做
- oracle - Oracle Database In-Memory 是内存数据库吗?
- reactjs - 如何在 React 中将组件放在 PWA 启动屏幕上
- next.js - Next.js 漂亮的 seo url 传递查询参数
- php - 如何修复 laravel 8 UI 分页问题不起作用
- python - 将每个日期多行的缺失日期添加到数据框中
- powershell - 使用 selenium powershell 参数化数据驱动测试
- node.js - 在 javascipt 中使用 ipfs:如何像从命令行将对象转储到文件并读取文件一样读取对象?
- java - 请求 uri 中的冒号是什么?