我正在使用googlemock做一些有趣的事情,并决定将我的类拆分为纯虚拟类和具体实现,以避免需要为我的模拟特殊外壳。但是,编译器开始抱怨:
error: undefined reference to 'vtable for <ConcreteClass>'
我设法通过以下方式重现了这个问题:
simple.h:
namespace simple {
class InterfaceA {
public:
virtual ~InterfaceA() {}
virtual int MethodOne() const = 0;
};
class InterfaceB : public InterfaceA {
public:
~InterfaceB() override {}
virtual int MethodTwo() const = 0;
};
class ImplA : public InterfaceA {
public:
ImplA(int to_return);
~ImplA() override {}
int MethodOne() const override;
private:
int to_return_;
};
class ImplB : public InterfaceB, public ImplA {
public:
ImplB();
~ImplB() override {}
// int MethodOne() const override;
int MethodTwo() const override;
};
} // namespace simple
simple.cc
#include "simple.h"
namespace simple {
ImplA::ImplA(int to_return) : to_return_(to_return) {}
int ImplA::MethodOne() const { return to_return_; }
ImplB::ImplB() : ImplA(5) {}
// int ImplB::MethodOne() const { return ImplA::MethodOne(); }
int ImplB::MethodTwo() const { return 2; }
} // namespace simple
问题是我评论过的内容;一旦我将这些东西添加到文件中,编译器和我的测试都很高兴。因此直观地说这是有道理的,因为现在有为虚拟方法定义的具体方法,并且编译器以前不会/不能猜测我想要的超类方法。
我的问题有两个:
ImplA::MethodOne()
的规范如何允许它被调用,因为它不是一个静态变量? ImplA
对象中的某个地方是否存在隐式ImplB
指针,允许它在ImplA
上调用方法,尽管它不是静态方法?答案 0 :(得分:2)
您具有菱形继承,因此在继承InterfaceA时需要指定虚拟关键字。请参阅代码here
#include <iostream>
using namespace std;
namespace simple {
class InterfaceA {
public:
virtual ~InterfaceA() {}
virtual int MethodOne() const = 0;
};
class InterfaceB : virtual public InterfaceA { // <-- note the virtual keyword
public:
~InterfaceB() override {}
virtual int MethodTwo() const = 0;
};
class ImplA : virtual public InterfaceA { // <-- note the virtual keyword
public:
ImplA(int to_return);
~ImplA() override {}
int MethodOne() const override;
private:
int to_return_;
};
class ImplB : public InterfaceB, public ImplA {
public:
ImplB();
~ImplB() override {}
//int MethodOne() const override;
int MethodTwo() const override;
};
ImplA::ImplA(int to_return) : to_return_(to_return) {}
int ImplA::MethodOne() const { return to_return_; }
ImplB::ImplB() : ImplA(5) {}
// int ImplB::MethodOne() const { return ImplA::MethodOne(); }
int ImplB::MethodTwo() const { return 2; }
} // namespace simple
int main() {
simple::ImplA implA(100);
cout << implA.MethodOne() << endl << endl;
simple::ImplB implB;
cout << implB.MethodOne() << endl;
cout << implB.MethodTwo() << endl;
return 0;
}
顺便说一下,你在问题中写过静态方法......那里没有静态方法,当你拨打ImplA::MethodOne()
时,你实际上打电话给this->ImplA::MethodOne()
。因此,调用IS绑定到this
的对象。
答案 1 :(得分:0)
您的ImplB
课程中有2 InterfaceA
个继承树。您需要使用虚拟继承(参见https://isocpp.org/wiki/faq/multiple-inheritance)。