链接其他文件中的函数时,在Qt上出现LNK 2019错误

时间:2019-06-06 09:35:23

标签: c++ qt user-interface

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

我已经尝试过再次运行qmake,清理并重建项目,并删除从头开始构建它的build文件夹,但是没有任何作用,还检查了我的.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;
}

container.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--;
    }
}

container.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文件,所以由于现在已经有很多代码,所以我现在不包括它。

我们将非常感谢所有帮助,非常感谢。

1 个答案:

答案 0 :(得分:0)

模板不是类。仅当将模板参数提供给它们时,它们才会被视为实现。话虽这么说,在您的cpp文件中,方法只是方法模板,还不是方法实现(尚未)。

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

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

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

另一种方法是在unique_ptr中的容器实例周围使用QListModelAdapter。 New仍然可以使用,您可以通过指针访问该对象。但是它将自动清除。

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

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

我在这里也看到了(这开始成为代码审查)是您的名字。 Q仅应使用Qt作为宏,函数名称,类名称等的前缀。如果有人使用您的代码,否则您的命名将使他们感到困惑。对于这样的用户,很可能您的类名是他们之前没有真正关注过的实际Qt类。