指针到成员函数和多重继承
Pointer-to-member-function and multiple inheritance
一个我无法控制的类Base
有一个函数,它接受指向任何类函数的成员指针。它旨在按如下方式使用:
class Derived : public Base {
void bindProperties() {
Base::bindProperty("answerswer", &Derived::getAnswer);
}
int getAnswer() const { return 42; }
};
某种方式(我既不知道也不关心),Base
存储此指针,稍后允许我调用Derived::get("answerswer")
(当然,这是一个简化的情况)。
缺点是,我们过去试图变得聪明,并使用了多重继承:
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("answerswer", &ICalculator::getAnswer); // (*)
}
};
认为多重继承还不错,只要我们只用它来继承一个接口,只有一个"具体"的基类。
模板化是因为有时我们想从Base
派生,有时从它的一个派生类(我也无权访问)派生 - 如果这无关紧要,你可以假装我写了Base
而不是T
并删除模板。
无论如何,我现在遇到的问题是,当我打电话时
LifeAndUniverseCalculator calc;
calc.bindProperties();
int answer = calc.get("answerswer");
我胡言乱语。我认为这可能是带有指向 vtables 的指针的东西,所以我尝试替换
T::bindProperty("answerswer", &ICalculator::getAnswer);
由
T::bindProperty("answerswer", &LifeAndUniverseCalculator::getAnswer);
希望它能正确计算偏移量,但显然这是行不通的(正如您现在已经发现的那样,我真的在猜测这一切是如何工作的)。
我想到了一些选择,例如
摆脱多重继承并将所有内容
ICalculator
直接放在LifeAndUniverseCalculator
中(这是唯一的派生类)为
LifeAndUniverseCalculator
中的所有ICalculator
东西创建包装函数,例如LifeAndUniverseCalculator::Calculator_GetAnswer
只是打电话给ICalculator::GetAnswer
.
我想知道
- 最好是,有没有办法以简单的方式修复标有(*)的行?
- 如果没有,最好的解决方案是什么(上面的替代方案之一,或其他)?
- 如果我能够联系班级
Base
的作者,并且他们愿意并且能够改变他们的班级,如果你能够根据我的描述说一些明智的话,我具体需要问什么。
如果您需要MCVE,我认为有一个可以解决IDEOne上的问题。
在 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
所做的吗 - 它将其他类的成员函数强制转换为自身的成员函数?(或者,也许,虽然我的修复使代码正常工作,但我错误地识别了问题)。
- 如何在 c++ 多重继承中调用父非虚函数?
- 多重继承导致虚假的模糊虚拟函数过载
- 带有此指针的模板类多重继承构造函数不起作用?
- 仅函数的多重继承 - 没有虚拟和 CRTP
- 从多重继承中的派生类函数调用适当的父类函数
- C++具有多重继承的构造函数重载解析
- 指针到成员函数和多重继承
- 使用具有虚拟多重继承的基构造函数
- 多重继承:调用所有覆盖的函数
- 具有虚拟多重继承的构造函数定义
- 实现具有多重继承的纯虚函数
- 多重继承析构函数调用他自己和父析构函数?c++
- 没有匹配的函数调用CTOR,多重继承
- 具有多重继承的纯虚函数重载和协变返回类型
- 多重继承、复制构造函数和基类初始化
- 在多重继承(菱形)中,祖父的默认构造函数称为
- 继承受保护的函数和公共变量C++时发生多重继承编译错误
- 纯虚拟函数和多重继承
- c++多重继承函数合并
- C++ 多重继承:函数不匹配