【发布时间】:2016-11-03 08:31:16
【问题描述】:
我想向下转换一个指向成员函数的指针,其中基类是虚拟继承的。这会导致编译时出错。
在我的应用程序中,我有几个对象的集合(例如D1、D2),它们有一个共同的基类B。它们通过std::vector<B*> 保持在一起并进行跟踪。
派生对象引入了需要定期调用的double-returning 函数。基类通过std::vector<double(B::*)(void)> 跟踪这些函数。整个链用在 main 函数的倒数第二行。
因此,在将函数指针添加到向量时,我需要转换函数指针,就像在派生类 D1 和 D2 的构造函数中所做的那样。他在D1 的情况下是成功的,但在D2 的情况下却不是,因为B 是D2 的虚拟基础。据我所知,在这种情况下静态转换不起作用(错误消息 1),因为派生类 D21 和 D22 只有一个指向 B 实例的指针。但是,dynamic_cast 也会导致编译时出错(错误消息 2),表示目标不是指针类型。
错误信息 1:错误:通过虚拟基 'B' 指向成员转换的指针 v.push_back(static_cast(&D2::f2));
错误消息 2:错误:不能 dynamic_cast '&D2::f2'(类型为 'double (class D2::)()')到类型 'double(class B: :)()'(目标不是指针或引用)
我想知道如何(如果有的话)执行所需的演员表。如果不是,我想知道为什么这样的事情是不可能的。
编辑:一些背景:我对常微分方程系统进行数值积分。派生类代表系统的各个方程,每个派生类计算自己的状态。通过收集向量o 中的类,我可以快速修改方程组。基类中的向量v 用于输出目的。在集成期间,每个子系统还通过基类处理自己的输出。钻石的出现是因为我将两段常用的代码分成了两个单独的类。
可以说,还有其他方法可以设计类层次结构,还有其他方法可以实现我的目标(在这种情况下,我将B 中的函数p 设为虚拟,并在派生类中重新实现它)。但是,我无法理解演员阵容失败的原因,所以我提出了这个问题。
MWE:
#include <vector>
#include <algorithm>
#include <iostream>
// Base class
class B {
protected:
std::vector<double(B::*)(void)> v;
public:
void p ( void )
{for_each(v.begin(), v.end(), [this] (double (B::*f) (void)) {std::cerr << (this->*f)() << std::endl;});};
};
// Normal inheritance
class D1: public B
{public:
double f1 ( void ) { return 1; }
D1() { v.push_back(static_cast<double(B::*)(void)>(&D1::f1));} // Casting is successful here.
};
// Setting up 'the diamond'
class D21: virtual public B {};
class D22: virtual public B {};
class D2: public D21, public D22
{public:
double f2 ( void ) { return 2; }
D2() { v.push_back(dynamic_cast<double(B::*)(void)>(&D2::f2)); } // How to cast here?
};
int main ()
{
// Vector holding the classes together
std::vector<B*> o;
// Set up the system
D1 d1;
D2 d2;
o.push_back(&d1);
o.push_back(&d2);
// Derived functions are called
for_each(o.begin(),o.end(),[] (B *o) {o->p();});
return 0;
}
【问题讨论】:
-
你能详细说明一下为什么你想做这样的事情吗? 原来的问题是什么?您想通过这样做解决什么用例? (Related reading about the XY problem)
-
dynamic_cast不能很好地处理“菱形”继承模式。使用reinterpret_cast(这是“我知道我在做什么”演员表)应该可以解决问题。 -
我看了here的答案,仍然不知道为什么我不能使用
dynamic_cast,因为我使用虚拟继承,我害怕使用reinterpret_cast。这在 MWE 中有效,但我昨天在完整的应用程序中尝试过,但没有编译。现在我觉得如果我使用它,并且它有效,它一定会失败。
标签: c++ casting member-function-pointers