gpt4 book ai didi

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

转载 作者:塔克拉玛干 更新时间:2023-11-03 07:09:33 24 4
gpt4 key购买 nike

我无法控制的类 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); // (*)
}
};

认为多重继承也不错,只要我们只用它来继承一个接口(interface),并且只有一个“具体”的基类。

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

无论如何,我现在遇到的问题是,当我调用

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

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

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

通过

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

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

我想到了一些方案,比如

  • 摆脱多重继承并将所有内容直接放入 ICalculatorLifeAndUniverseCalculator(它是唯一的派生类)

  • LifeAndUniverseCalculator 中的所有 ICalculator 内容创建包装函数,例如LifeAndUniverseCalculator::Calculator_GetAnswer 只是调用 ICalculator::GetAnswer

我想知道

  • 最好有一种简单的方法来修复标有 (*) 的行?
  • 如果不是,最好的解决方案是什么(上述备选方案之一,或其他方案)?
  • 如果我能够联系 Base 类的作者并且他们愿意并且能够更改他们的类,那么我需要具体问什么,如果你能说一些明智的基于根据我的描述。

如果您需要 MCVE,我认为有一个解决了问题 on 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++ - 指向成员函数的指针和多重继承,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/44006566/

24 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com