QT c++多重定义和首次定义这里报错

QT c++ multiple definition and first defined here error

我在 main.cpp 文件中添加了一个部分,要求在 window 打开之前输入密码。它从 help.h 和 cnstnt.h 文件中获取所需内容。然后我创建了一个名为设置的对话框,并尝试在这里更改密码。它在我之前的测试项目中运行良好,但是当我在这个项目中使用相同的东西时,我遇到了一个 first defined here 错误。我检查过,我做了 运行 qmake 和重建,但没有任何改变。我该如何解决这个问题?我是 C++ 和 QT 的新手。

这是我的代码

main.cpp

#include "mainwindow.h"

#include <QApplication>
#include <QMessageBox>
#include "cnstnt.h"
#include "help.h"

int main(int argc, char *argv[])
{
    QApplication a(argc, argv);
    a.setStyle("fusion");
    a.setQuitOnLastWindowClosed(false);
    MainWindow w;


     QString login = QInputDialog::getText(NULL, "Login","username",QLineEdit::Normal);

       if (login == cnstnt::username)
       {

            QString getPassword = QInputDialog::getText(NULL, "Login","password",QLineEdit::Password);


            QString hashpassword = hlpr::hashPassword(getPassword.toUtf8());

            if(hashpassword == hlpr::getTxtPassword()){

                   w.show();
            }else{
                QMessageBox::warning(nullptr, "error!", "wrong password!");
            }

       }
       else
       {
           QMessageBox::warning(nullptr, "error!", "wrong username!");


       }


      return a.exec();

}

cnstnt.h

#ifndef CNSTNT_H
#define CNSTNT_H

#include <QtWidgets>


namespace cnstnt {
   QString TEXT_DIR = QStandardPaths::writableLocation(QStandardPaths::DocumentsLocation) + "/test/password.txt";


   QString username = "admin";


}
#endif // CNSTNT_H

help.h

#ifndef HELP_H
#define HELP_H


#include <QCryptographicHash>


#include "cnstnt.h"

namespace hlpr {


    // login actions
    QString hashPassword(QByteArray str){
        QByteArray step1 = QCryptographicHash::hash((str),QCryptographicHash::Md5).toHex();
        QString lastHash = QString(QCryptographicHash::hash((step1),QCryptographicHash::Sha512).toHex());
        return lastHash;
    }

    QString getTxtPassword(){
        QString currentPassword;
        QFile file(cnstnt::TEXT_DIR);
           if (file.open(QIODevice::ReadOnly | QIODevice::Text)){
               QTextStream in(&file);
               currentPassword = in.readLine();
               file.close();
           }
           return currentPassword;
    }

    bool setTxtPassword(QString newPass){
        QFile file(cnstnt::TEXT_DIR);
        if(file.open(QIODevice::WriteOnly | QIODevice::Truncate)){
            QTextStream stream(&file);
            QByteArray newPassType = newPass.toUtf8();
            stream << hashPassword(newPassType);
            file.close();
            return true;
        }
        return false;
    }


}
#endif // HELP_H

settingdialog.h

#ifndef SETTINGDIALOG_H
#define SETTINGDIALOG_H

#include <QDialog>
#include <QMessageBox>
#include "help.h"


namespace Ui {
class settingDialog;
}

class settingDialog : public QDialog
{
    Q_OBJECT

public:
    explicit settingDialog(QWidget *parent = nullptr);
    ~settingDialog();

private slots:
    void on_pushButton_8_clicked();

private:
    Ui::settingDialog *ui;
};

#endif // SETTINGDIALOG_H

settingdialog.cpp

#include "settingdialog.h"
#include "ui_settingdialog.h"


settingDialog::settingDialog(QWidget *parent) :
    QDialog(parent),
    ui(new Ui::settingDialog)
{
    ui->setupUi(this);
}

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

void settingDialog::on_pushButton_8_clicked()
{
 QString TEXT_DIR = QStandardPaths::writableLocation(QStandardPaths::DocumentsLocation) + "/test/password.txt";
    QString savedPassword = hlpr::getTxtPassword();

    QString curPassword = ui->oldPassBox->text();
    QString newPass = ui->newPassBox->text();
    QString confirmPass = ui->confirmPass->text();
    QByteArray curHash = curPassword.toUtf8();

    if(newPass != confirmPass) {
        QMessageBox::information(this, "Bilgi", "Yeni şifreniz ile tekrarı eşleşmiyor!");
     }else if(newPass == curPassword){
        QMessageBox::information(this, "Bilgi", "Mevcut şifreniz ile yeni şifreniz ile aynı olamaz!");
    }else if(savedPassword != hlpr::hashPassword(curHash)) {
        QMessageBox::information(this, "Bilgi", "Mevcut şifreniz hatalı!");
    }else{
       bool status = hlpr::setTxtPassword(newPass);
       if(status){
           ui->oldPassBox->clear();
           ui->newPassBox->clear();
           ui->confirmPass->clear();
           QMessageBox::information(this, "Başarılı", "Şifreniz başarıyla güncellendi.");
       }else{
           QMessageBox::warning(this, "Hata!", "Şifreniz güncellenirken hata oluştu!");
       }
    }



}

错误

  1. X:\DataLoggerQT\QtSerialMonitor-master\src\help.h:11: 错误: hlpr::passwordHash(QByteArray)' debug/mainwindow.o: In function ZSt19__iterator_categoryIPK7QStringENSt15iterator_traitsIT_E17iterator_categoryERKS4_'的多重定义: X:\DataLoggerQT\QtSerialMonitor-master\build-QtSerialMonitor-Desktop_Qt_5_15_2_MinGW_32_bit-Debug/../src/help.h:11: `hlpr::passwordHash(QByteArray)'的多重定义
  2. X:\DataLoggerQT\QtSerialMonitor-master\src\help.h:11: 首先定义 这里
  3. X:\DataLoggerQT\QtSerialMonitor-master\src\help.h:28: 错误:hlpr::setTxtPassword(QString)' debug/moc_mainwindow.o: In function ZN4hlpr14setTxtPasswordE7QString' 的多重定义: X:\DataLoggerQT\QtSerialMonitor-master\build-QtSerialMonitor-Desktop_Qt_5_15_2_MinGW_32_bit-Debug/debug/../../src/help.h:28: `hlpr::setTxtPassword(QString)'
  4. 的多重定义

您已将 helper.h 包含在两个 header 文件中 - settingdialog.h 和 main.cpp,mainwindow.h 包含在 main.cpp 中,我假设,包括 settingdialog.h 本身。或者,也许,它是通过任何其他包含 header 包含的。所以你有多个定义错误,每个包含一个。 为避免此类错误,helper.h 文件中的函数应使用 extern 关键字声明,并将其实现移至 helper.cpp 文件。它可以防止您将来遇到任何潜在的问题。而且您应该始终以这种方式声明函数。 最后,您不需要在 settingdialog.h 中包含 helper.h,因为您在 cpp 中使用它的功能。将包含移动到 settingdialog.cpp。请记住,只在真正使用文件的地方包含文件,这样可以最大程度地减少编译时间。