指向成员函数的指针和多重继承

Pointer-to-member-function and multiple inheritance

我无法控制的

A class Base 有一个函数接受指向任何 class 函数的成员指针。它的用途如下:

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);  // (*)
  }
};

认为多重继承也不错,只要我们只用它来继承一个接口,而且只有一个"concrete"基class.

模板化是因为有时我们想从 Base 派生,有时我们想从它派生的 classes 之一派生(我也无权访问)- 如果那与你无关可以假装我写了 Base 而不是 T 并删除模板。

无论如何,我现在遇到的问题是,当我打电话给

LifeAndUniverseCalculator calc;
calc.bindProperties();
int answer = calc.get("answer");

我胡言乱语。我想它可能是指向 vtables 的指针,所以我尝试替换

    T::bindProperty("answer", &ICalculator::getAnswer);

来自

    T::bindProperty("answer", &LifeAndUniverseCalculator::getAnswer);

希望它能正确计算偏移量,但显然这行不通(正如你现在已经知道的,我真的在猜测这一切是如何工作的)。

我想到了一些方案,比如

我想知道

如果您需要 MCVE,我认为有一个解决了问题 on IDEOne

在您的 MCVE 中,函数 A::bindFunction(类似于简化代码中的 Base::bindProperty)强制将 B 的函数成员强制转换为 [=15= 的成员函数].这让我觉得这是根本问题。这可以通过将 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

但是,我知道我更改的代码属于您明确提到的不能修改的 class。这确实是 Base 所做的——它将其他 class 的成员函数转换为它自己的成员函数吗? (或许,虽然我的修复使代码正常工作,但我错误地识别了问题)。