链接另一个文件中的函数时,Qt 上出现错误 LNK 2019

Error LNK 2019 on Qt while linking a function from another file

本文关键字:错误 2019 LNK Qt 文件 另一个 函数 链接      更新时间:2023-10-16

我正在Windows x86机器上使用Qt版本4.7.2的大学项目(我使用的是旧版本,因为我们的老师将使用此版本来审查该项目),但是在将某些功能从类容器链接到类QListModelAdapter时遇到了一些问题。

我已经尝试再次运行qmake,清理并重建项目并删除用于从头开始构建它的构建文件夹,但这些都不起作用,还检查了我的.pro文件,但似乎没有什么问题。

qlistmodeladapter.h

#ifndef QLISTMODELADAPTER_H
#define QLISTMODELADAPTER_H
#include <QAbstractListModel>
#include "container.h"
class AddLayout;
class QListModelAdapter : public QAbstractListModel {
private:
Container<articolo>* model;
const AddLayout* insert;
public:
QListModelAdapter(QObject* = nullptr, const AddLayout* = nullptr);
~QListModelAdapter() override;
bool insertRows(int, int = 1, const QModelIndex& = QModelIndex()) override;
bool removeRows(int, int = 1, const QModelIndex& = QModelIndex()) override;
};
#endif

qlistmodeladapter.cpp

#include "qlistmodeladapter.h"
#include "container.h"
#include "addlayout.h"
#include <QFont>
QListModelAdapter::QListModelAdapter(QObject* parent, const AddLayout* ins) :
QAbstractListModel(parent),
model(new Container<articolo>()), insert(ins) {}
bool QListModelAdapter::removeRows(int begin, int count, const QModelIndex& parent) {
beginRemoveRows(parent, begin, begin + count - 1);
model->removeEl(begin);
endRemoveRows();
return true;
}
bool QListModelAdapter::insertRows(int begin, int count, const QModelIndex& parent) {
beginInsertRows(parent, begin, begin + count - 1);
articolo art = articolo(new Computer(insert->getNome()));
model->insertEl(art);
endInsertRows();
return true;
}

容器.cpp

#include "container.h"
template<class T>
void Container<T>::insertEl(T& p)
{
if (maxSize == size)
{
increaseSize();
}
iteratore it = end();
*(it) = p;
size++;
}
template<class T>
void Container<T>::removeEl(int j)
{
if (j <= size)
{
iteratore it = begin();
for(int i = 0; i <= (j-1); i++)
{
it++;
}
delete it.punt;
iteratore aux = it;
it++;
for(int i = j; i < size-2; i++)
{
aux = it;
aux++;
it++;
}
size--;
}
}

容器.h

#ifndef CONTAINER_H
#define CONTAINER_H
#include "items.h"
template<class T>
class Container
{
friend class iteratore;
private:
T* vector;
int size;
int maxSize;
public:
class iteratore {
// is defined correctly
};
Container(T* p = nullptr, int s = 0);//it is defined but not included
void removeEl(int);
void insertEl(T&);
};
#endif // CONTAINER_H

有罪的函数是 removeEl,并且在哪里得到此错误:

qlistmodeladapter.obj:-1: error: LNK2019: riferimento al simbolo esterno "public: void __cdecl Container<class articolo>::removeEl(int)" (?removeEl@?$Container@Varticolo@@@@QEAAXH@Z) non risolto nella funzione "public: virtual bool __cdecl QListModelAdapter::removeRows(int,int,class QModelIndex const &)" (?removeRows@QListModelAdapter@@UEAA_NHHAEBVQModelIndex@@@Z)

抱歉,该语言设置为意大利语,奇怪的是它与 insertEl 一起工作,所以我不知道该怎么想。

我已经检查了 .pro 文件,所以我现在不包括它,因为已经有很多代码了。

每一个帮助将不胜感激,非常感谢。

模板不是类。只有当给他们一个模板参数时,他们才会被视为实现。话虽如此,在您的 cpp 文件中,这些方法只是方法模板,它们(还)不是方法实现。

现在,当您尝试从不同的翻译单元(cpp 文件)调用该方法时,链接器将尝试查找方法实现的符号,但找不到它,因为编译器不会在 cpp 文件中创建相应的符号,因为它从未使用相应的模板参数调用过。

解决方案非常简单:无论谁使用您的模板,都需要提供方法模板,以便调用方法模板将敦促编译器创建此所需的实现 ->方法实现移动到头文件。您可以完全删除此类模板的 cpp 文件。

编辑:顺便说一下,您在此处创建内存泄漏,因为您在容器类上调用new但从不删除。这里有两种明确的可能性:由于您使用Qt,因此您可以通过让Container继承QObject来使用它的内存管理。然后,在构造函数中,使用列表视图传递给它的父级初始化QObject

另一种方法是在QListModelAdapter中围绕容器实例使用unique_ptr。New 仍然有效,您可以通过指针访问对象。但它会自动清理。

当然,您也可以在没有指针的情况下将Container放在堆栈上(只需删除*并使用.访问对象)。

请注意,在您自己的析构函数中手动调用delete不是新式C++。它使事情变得更加复杂,您还需要实现复制构造函数和复制赋值运算符。这在2019年不再是必要或可推荐的。C++是一种新鲜的语言,现在习惯使用时有多种防止内存泄漏的方法。

我也在这里看到(这开始成为代码审查)是你的命名。Q作为宏的前缀,函数名、类名等应该只由Qt使用。如果有人使用您的代码,否则他们会对您的命名感到困惑。对于这样的用户,很可能你的类名是一个实际的Qt类,他们以前没有心