我无法控制的类Base
有一个函数接受指向任何类函数的成员指针。它的用法如下:
class Derived : public Base {
void bindProperties() {
Base::bindProperty("answer", &Derived::getAnswer);
}
int getAnswer() const { return 42; }
};
某种方式(我既不知道也不关心),Base
存储此指针,后来允许我调用Derived::get("answer")
(当然,这是一种简化的情况)。
缺点是,我们过去曾试图变得聪明,并使用了多重继承:
class ICalculator {
virtual int getAnswer() const;
};
template<class T>
class LifeAndUniverseCalculator : public T, public ICalculator {
virtual int getAnswer() const /* override */ { return 42; }
void bindProperties() {
T::bindProperty("answer", &ICalculator::getAnswer); // (*)
}
};
认为多重继承并不坏,只要我们只使用它继承一个接口并且只有一个“具体”基类。
模板是因为有时候我们想要从Base
派生,有时候从它的一个派生类派生(我也无法访问) - 如果这是无关紧要的,你可以假装我写{{1而不是Base
并删除模板。
无论如何,我现在遇到的问题是,当我打电话时
T
我得到了胡言乱语。我认为它可能是指向vtable的指针,所以我尝试替换
LifeAndUniverseCalculator calc;
calc.bindProperties();
int answer = calc.get("answer");
通过
T::bindProperty("answer", &ICalculator::getAnswer);
希望能正确计算偏移量,但显然不起作用(正如你现在已经想到的那样,我真的第二次猜测这一切是如何起作用的。)
我想到了一些选项,比如
摆脱多重继承并将 T::bindProperty("answer", &LifeAndUniverseCalculator::getAnswer);
中的所有内容直接放入ICalculator
(这是唯一的派生类)
为LifeAndUniverseCalculator
中的所有ICalculator
内容创建包装函数,例如LifeAndUniverseCalculator
只需拨打LifeAndUniverseCalculator::Calculator_GetAnswer
。
我想知道
ICalculator::GetAnswer
的作者并且他们愿意并且能够改变他们的班级,那么具体我需要问什么,如果你能根据我的描述说些合理的话如果您需要MCVE,我认为有一个可以捕获问题on IDEOne。
答案 0 :(得分:1)
在你的MCVE中,函数A::bindFunction
(类似于简化代码中的Base::bindProperty
)强制将B
函数的成员强制转换为A
的成员函数。这是根本问题。可以通过将A::f
的类型更改为std::function<int(void)>
:
class A
: public ABase {
public:
// int a, b;
class Unknown{};
typedef int(A::*Function)();
template<typename T, typename Func>
void bindFunction(T* owner, Func myf) {
f = std::bind(myf,owner);
}
int call() {
return f();
}
//Function f;
std::function<int(void)> f;
};
...
class Combined
: public A, public B {
public:
Combined(int value) : B(value), A() {}
virtual void /*A::*/bind() /* override */ {
A::bindFunction( this, &Combined::getValue );
}
};
只有这个改变,你的MCVE才能工作,打印出来
The answer to Life, The Universe and Everything is 42
但是,我知道我更改的代码属于您明确提到的无法修改的类。这确实是Base
的作用 - 它将其他类的成员函数强制转换为其自身的成员函数吗? (或许,当我的修复程序使代码工作时,我错误地识别了问题)。