You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

QT C++子类化QLineEdit时构造函数报未定义引用错误如何解决

问题说明

子类化QLineEdit实现自定义方向键响应逻辑时,编译阶段报链接错误:

undefined reference to "DataLineEdit::DataLineEdit(QWidget*)

目标是用自定义的DataLineEdit替换DataWidget中动态创建的原生QLineEdit实例,其余行为保持和原生控件一致。

相关代码

datalineedit.h

#ifndef DATALINEEDIT_H
#define DATALINEEDIT_H

#include <QLineEdit>
#include <QWidget>

class DataLineEdit: public QLineEdit
{
    Q_OBJECT

public:
    explicit DataLineEdit(QWidget *parent = 0);
    ~DataLineEdit();


protected:
    void keyPressEvent(QKeyEvent* event);


signals:
    void leftRightOverrideKeyPress(int state);

private:


};

#endif // CUSTOMLINEEDIT_H

datalineedit.cpp

#include "datalineedit.h"
#include<QKeyEvent>



DataLineEdit::DataLineEdit(QWidget*parent) : QLineEdit(parent)
{

}

DataLineEdit::~DataLineEdit()
{

}

void DataLineEdit::keyPressEvent(QKeyEvent *event)
{
    if(event->key() == Qt::Key_Left && this->cursorPosition() == 0)
    {
        emit leftRightOverrideKeyPress(0);
    }
    else if(event->key() == Qt::Key_Right && this->cursorPosition() == 2)
    {
        emit leftRightOverrideKeyPress(1);
    }
    else
    {
        QLineEdit::keyPressEvent(event);
    }
}

datawidget.h

#define DATAWIDGET_H

#include <QFile>
#include <QFileDialog>
#include <QTextStream>
#include <QMessageBox>
#include <QLineEdit>
#include <QObject>
#include <QtCore>
#include <QtGui>
#include <QKeyEvent>
#include <QMainWindow>
#include "datalineedit.h"

extern int focusRow;
extern int focusCol;
extern int numRows;
extern int numBottomRowCols;

extern QLineEdit *focusedLineEdit;

namespace Ui{
class DataWidget;
}

class QLineEdit;
class QLabel;

class DataWidget : public QWidget
{
    Q_OBJECT

public:
    explicit DataWidget(QWidget *parent = 0);
    ~DataWidget();

    QString data;

protected:
    bool eventFilter(QObject *object, QEvent *event);

public slots:
    void focusChanged(QWidget *old, QWidget *now);
    void arrowKeyNavigation(int state);
    void on_applyChangePushButton_clicked();
    void setData(QString text);
    QString getData();

private slots:

    void updateDataGridVisibility();

    void on_payloadLineEdit_textChanged(const QString &arg1);

    void on_savePushButton_clicked();

    void on_openPushButton_clicked();

    void on_presetComboBox_currentIndexChanged(int index);

private:
    Ui::DataWidget *ui;
    QString currentFile = "";
};

#endif // DATAWIDGET_H

datawidget.cpp

#include "datawidget.h"
#include "datawidget.h"
#include "datalineedit.h"

#include <QGridLayout>
#include <QLineEdit>
#include <QGroupBox>
#include <QKeyEvent>
#include <QIntValidator>

int focusRow;
int focusCol;
int numRows;
int numBottomRowCols;

QLineEdit *focusedLineEdit;

enum key_directions
{
    arrowLeft = 0,
    arrowRight = 1,
    arrowUp = 2,
    arrowDown = 3
};

enum presets
{
    preset1 = 0,
    preset2 = 1,
    preset3 = 2,
    preset4 = 3,
    preset5 = 4,
    clean = 5,
    zeroes = 6
};

DataWidget::DataWidget(QWidget *parent) :
    QWidget(parent),
    ui(new Ui::DataWidget)
{

    ui->setupUi(this);
    this->installEventFilter(this);

    connect(qApp, SIGNAL(focusChanged(QWidget*, QWidget*)), this, SLOT(focusChanged(QWidget*,QWidget*)));

    //payloadLineEdit
    ui->payloadLineEdit->setValidator(new QIntValidator(0,64, this));
    ui->payloadLineEdit->setFixedSize(20,20);
    ui->payloadLineEdit->setTextMargins(0,0,0,0);

    //dataGridLayout
    ui->dataGridLayout->setAlignment(Qt::AlignLeft);
    ui->dataGridLayout->setAlignment(Qt::AlignTop);

    for(int i=0; i<4; i++)
    {
        for(int j=0; j<16; j++)
        {
            DataLineEdit *lineEdit = new DataLineEdit();
            lineEdit->setText("00");//set data default
            lineEdit->setInputMask("Hh");//limit to hex values
            lineEdit->setFixedSize(20,20);
            lineEdit->setTextMargins(0,0,0,0);
            lineEdit->setAlignment(Qt::AlignCenter);
            lineEdit->setAlignment(Qt::AlignCenter);
            connect(lineEdit, SIGNAL(leftRightOverrideKeyPress(int)), this, SLOT(arrowKeyNavigation(int)));

            ui->dataGridLayout->addWidget(lineEdit, i, j);

        }
    }

    updateDataGridVisibility();
}



DataWidget::~DataWidget()
{
    delete ui;
}

void DataWidget::arrowKeyNavigation(int state)
{
//does something
}

错误截图

错误截图

解决方案

这个错误是典型的Qt MOC(元对象编译器)未正确处理带Q_OBJECT宏的类导致的链接错误,按以下步骤排查修复:

  1. 确认项目构建配置正确
    • 如果使用qmake构建,检查.pro文件中是否已经把datalineedit.h加入HEADERS列表、datalineedit.cpp加入SOURCES列表,示例配置:
      QT += core gui widgets
      TARGET = YourProjectName
      TEMPLATE = app
      HEADERS += datalineedit.h datawidget.h
      SOURCES += datalineedit.cpp datawidget.cpp main.cpp
      
    • 如果使用CMake构建,确认datalineedit.cpp在add_executable/add_library的源文件列表中,且已经正确链接Qt::Widgets模块。
  2. 执行完整清理重编译
    新增带Q_OBJECT宏的类后,增量编译通常不会自动触发MOC处理新类,需要先删除整个构建目录(或执行构建系统的clean命令,删除所有moc_.cpp、.o中间文件),重新运行qmake/CMake生成构建配置,再全量编译。
  3. 修复代码中的低级错误
    • datalineedit.h末尾的头文件守卫注释错误,将#endif // CUSTOMLINEEDIT_H改为#endif // DATALINEEDIT_H,避免后续维护混淆。
    • datawidget.h开头缺少头文件守卫判断,在第一行#define DATAWIDGET_H前补上#ifndef DATAWIDGET_H,防止头文件重复包含引发异常。
    • datawidget.cpp中重复引入了两次datawidget.h,删除重复的include行。
可选优化
  • datalineedit.cpp中#include<QKeyEvent>改为#include <QKeyEvent>,符合通用编码规范。
  • 右箭头判断逻辑cursorPosition() == 2可以加注释说明是对应2位十六进制输入的最右光标位置,后续修改输入长度时不容易出问题。
  • 动态创建DataLineEdit时建议传入父对象:new DataLineEdit(this),交由Qt对象树管理内存,避免内存泄漏。

内容的提问来源于stack exchange,提问作者Zachary Hicks

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.08.26 16:06:22