将类声明放入.cpp文件中
Putting class declaration in .cpp file
是否可以在相同的。cpp文件中进行类声明和实现?
我想在mock对象的帮助下做一些单元测试。下面是我测试的一些例子:
// Some includes removed
#include "abstractconnection.h"
class ConnectionMockup : public AbstractConnection
{
Q_OBJECT
public:
explicit ConnectionMockup(QObject *parent = 0);
bool isReady() const;
void sendMessage(const QString &message);
void test_send_message(const QString &message);
bool ready;
QStringList messages;
};
ConnectionMockup::ConnectionMockup(QObject *parent)
: AbstractConnection(parent)
{
ready = true;
}
bool ConnectionMockup::isReady() const
{
return ready;
}
void ConnectionMockup::sendMessage(const QString &message)
{
messages.append(message);
}
void ConnectionMockup::test_send_message(const QString &message)
{
emit messageRecieved(message);
}
TestEmcProgram::TestEmcProgram(QObject *parent) :
QObject(parent)
{
}
void TestEmcProgram::open()
{
ConnectionMockup mockup;
EmcProgram program(&mockup);
QCOMPARE(...
...
...
可以看到,类ConnectionMockup仅由类TestConnection使用,我在其他任何地方都不需要它。因此,当我尝试编译这个程序时,我得到以下错误:
> testemcprogram.o: In function
> `ConnectionMockup':
> /home/sasa/Desktop/QtPro/FocoKernel-build-desktop/../FocoKernel/testemcprogram.cpp:29:
> undefined reference to `vtable for
> ConnectionMockup'
> /home/sasa/Desktop/QtPro/FocoKernel-build-desktop/../FocoKernel/testemcprogram.cpp:29:
> undefined reference to `vtable for
> ConnectionMockup' testemcprogram.o: In
> function `~ConnectionMockup':
> /home/sasa/Desktop/QtPro/FocoKernel-build-desktop/../FocoKernel/testemcprogram.cpp:14:
> undefined reference to `vtable for
> ConnectionMockup'
是否可以在这里留下声明,或者我必须创建头文件并将声明移动到该文件中?
编辑:由于Jerry Coffin先生(谢谢Coffin先生)建议我可能不实现一些虚函数,我将在这里声明AbstractConnection,以便我们可以审查这种可能性:
#include <QObject>
class AbstractConnection : public QObject
{
Q_OBJECT
public:
explicit AbstractConnection(QObject *parent = 0);
virtual ~AbstractConnection();
virtual bool isReady() const = 0;
signals:
void messageRecieved(const QString &message);
public slots:
virtual void sendMessage(const QString &message) = 0;
};
解决方案:感谢@JCooper, @iammilind和@Jerry Coffin,我们有了解决方案。在从AbstractConnection中删除析构函数(因为它实际上什么都不做)并从ConnectionMockup中删除Q_OBJECT之后,它就可以工作了。
Q_OBJECT
宏声明了一组元对象成员函数。MOC构建工具负责解析.h文件并定义这些函数声明。注意,它不解析.cpp文件。在您的情况下,无法找到vtable
,因为MOC工具没有解析您的.cpp文件。解决方案是将类定义移动到头文件中,并将头文件添加到.pro文件中。第二个解决方案(有点"黑客")是执行以下操作:
#include <QObject>
#include <QtDebug>
class Counter : public QObject
{
Q_OBJECT
public:
Counter() { value = 0; }
int getValue() const { qDebug() << "getValue()"; return value; }
public slots:
void setValue(int value);
signals:
void valueChanged(int newValue);
private:
int value;
};
#include "main.moc"
void Counter::setValue(int value)
{
qDebug() << "setValue()";
if (this->value != value) {
this->value = value;
emit valueChanged(value);
}
}
int main()
{
Counter a, b;
QObject::connect(
&a, &Counter::valueChanged,
&b, &Counter::setValue);
a.setValue(12);
b.setValue(48);
return 0;
}
注意' #include "myfile。类定义下的Moc"。
这样做是因为qmake会在任何带有#include指令的文件上调用MOC工具。因此,MOC将解析.cpp文件并生成元对象函数定义,从而解决链接器错误。
是的,在单个文件中定义类及其成员函数是完全合法和允许的。事实上,从编译器的角度来看,本质上总是这样——你在头文件中有类定义,并将该头文件包含在实现其成员函数的源文件中。
您遇到的错误看起来像是链接器错误,而不是编译器错误。从你发布的信息中还不完全清楚到底缺了什么。一种可能性是你的基类有一些你没有在派生类中实现的纯虚函数,但是我完全不确定这是正确的。
当基类有非纯的virtual
函数时,在编译最终二进制文件时需要包含该函数的定义,否则会导致vtable
或typeinfo
的链接错误。看下面的例子:
// Base.h
struct Base {
virtual void fun() = 0;
virtual ~Base();
};
// Base.cpp
#include"Base.h"
Base::~Base () {}
// Derived.cpp
#include"Base.h"
struct Derived : Base {
void fun () {}
};
int main () {
Derived d;
}
现在,Derived.cpp和Base.cpp的编译链接将正常工作。两个。cpp文件也可以分别编译以创建目标文件,然后链接在一起。
从你的问题来看,我的感觉是,你没有以某种方式附加class AbstractConnection
的.cpp/object文件,它仍然包含一个非纯虚函数——它的destructor
。如果您将该定义与ConnectionMockup
一起编译,则不应出现链接器错误。您可以编译包含析构函数体的文件,也可以在类定义本身中定义析构函数体。
- 为什么两个不同的未命名名称空间可以共存于一个cpp文件中
- 命名空间中具有.h和.cpp文件的类
- 无法编译 rtmidi 测试 cmidiin.cpp 文件, 非法指令
- C++-试图将函数指针推回到另一个CPP文件中的矢量时出错
- 有充分的理由在h文件中使用include保护而不是cpp文件吗
- 如何在cpp文件之间切换窗口?在Qt中
- 在 .h 文件中的类中声明静态变量和在.cpp文件中声明"global"变量有什么区别
- 我有两个类需要在同一 cpp 文件中相互引用,但第一个类无法识别第二个类类型的对象
- .h 和.cpp文件分离时出错,但仅使用 .h 文件时没有错误.我做错了什么?
- 库标题在标题中不可见,但在 cmake build 下.cpp文件中完全可见.为什么?
- C++ 链接到单独的.cpp文件说"multiple definitions"
- 在 cpp 文件中隐藏采用模板参数引用的方法
- 如何使用 samtools C API 构建一个简单的主.cpp文件
- 包含在.cpp文件中包含在 .h 文件时包含
- C++(.cpp文件和.h文件)拆分代码并添加一个函数,提取 - 这很容易吗?
- 在头文件和 cpp 文件中使用一次 #pragma 时出现结构重定义错误
- 如何使用线程类编译 cpp 文件?
- 使用 Powershell 命令将 cpp 文件的文件夹编译为 GNU 的 g++
- 我应该将外部标头放在 .h 文件还是.cpp文件中?
- 从另一个 cpp 文件更改结构内、映射键内的变量