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!");
}
}
}
错误
- 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)'的多重定义
- X:\DataLoggerQT\QtSerialMonitor-master\src\help.h:11: 首先定义
这里
- 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)' 的多重定义
您已将 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。请记住,只在真正使用文件的地方包含文件,这样可以最大程度地减少编译时间。
我在 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!");
}
}
}
错误
- 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)'的多重定义 - X:\DataLoggerQT\QtSerialMonitor-master\src\help.h:11: 首先定义 这里
- 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)' 的多重定义
您已将 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。请记住,只在真正使用文件的地方包含文件,这样可以最大程度地减少编译时间。