【发布时间】:2018-12-14 02:45:16
【问题描述】:
我最近的工作任务是尝试将 C++ 项目从旧的 Windws 2003 服务器迁移到 Windows 2008。 目前,我正在尝试在我的 Windows 7PC 上本地构建应用程序。 我已按照收到的安装指南进行操作。事情似乎进展得很好。 我遇到的问题是,在编译步骤之后,链接器给了我以下错误:
msvcprtd.lib(MSVCP90D.dll) : error LNK2005: "class std::basic_ostream<char,struct std::char_traits<char> > & __cdecl std::operator<<<struct std::char_traits<char> >(class std::basic_ostream<char,struct std::char_traits<char> > &,char const *)" (??$?6U?$char_traits@D@std@@@std@@YAAAV?$basic_ostream@DU?$char_traits@D@std@@@0@AAV10@PBD@Z) already defined in CellSortTypeIds.obj
顺便说一下,这是在调试模式下运行的。在发布模式下,我遇到了同样的错误。 我可以给你看对应的CPP文件:
-
CellSortTypeIds.h 文件:
#ifndef CELL_SORT_TYPE_IDS_H #define CELL_SORT_TYPE_IDS_H #include <iostream> #include <QtCore/QString> namespace CellSortTypeIds { enum CellSortTypeEnum { NAME=0, LAC, CI, NB_ITEMS }; static const QString mStrings[] = { QT_TR_NOOP("Tri par code Nom"), QT_TR_NOOP("Tri par code LAC"), QT_TR_NOOP("Tri par code CI") }; QString getQString(const CellSortTypeIds::CellSortTypeEnum aCellSortType); CellSortTypeEnum getCellSortTypeFromQString( QString aCellSortType ); } std::ostream& operator <<(std::ostream &, const CellSortTypeIds::CellSortTypeEnum&); #endif //CELL_SORT_TYPE_IDS_H -
CellSortTypeIds.cpp 文件
#include "CellSortTypeIds.h" #include <QtCore/QObject> using namespace std; ostream& operator <<(ostream &out, const CellSortTypeIds::CellSortTypeEnum& aCellSortType) { out << CellSortTypeIds::getQString(aCellSortType).toAscii().operator const char*(); return out; } QString CellSortTypeIds::getQString(const CellSortTypeIds::CellSortTypeEnum aCellSortType) { QString result(""); if( aCellSortType < CellSortTypeIds::NB_ITEMS ) { result = QObject::tr( CellSortTypeIds::mStrings[aCellSortType].toAscii().data() ); } else { cerr << __FILE__<< "(" <<__LINE__ << "): mStrings[" << (int)aCellSortType << "] not initialised" << endl; } return result; } CellSortTypeIds::CellSortTypeEnum CellSortTypeIds::getCellSortTypeFromQString( QString aCellSortTypeString ) { CellSortTypeIds::CellSortTypeEnum theEnum( CellSortTypeIds::NAME ); bool found( false ); for( int index( 0) ; index < CellSortTypeIds::NB_ITEMS && !found ; index++ ) { if( QObject::tr(CellSortTypeIds::mStrings[ index ].toAscii().data()) == aCellSortTypeString ) { theEnum = (CellSortTypeIds::CellSortTypeEnum)index; found = true; } } return theEnum; }
我的 C++ 知识不是很好。我已经阅读了关于这个问题的几篇关于 SO 的帖子,一些关于配置的运行时,一些关于不在头文件中定义运算符,而是将它们放在 cpp 文件中。这里我相信不是这样的。
我怀疑这两个文件中存在我无法弄清楚的问题。 任何想法都值得赞赏。如果您需要更多详细信息,请告诉我。 提前感谢您,请不要犹豫就问题的结构提供任何反馈,因为这是我的第一个问题。
【问题讨论】:
-
@BoPersson 鉴于他们得到了它的安装指南,我不认为提问者编写了代码。现在他们只是在尝试构建它。
-
如果只是注释掉
.cpp中的所有流操作,是否还会出现链接器错误?如果不是,是哪些原因造成的? -
@BoPersson Max 是正确的,我还没有过多考虑项目的内容,因为主要目标是让它在更新的机器上运行。但是,根据stackoverflow.com/questions/18693866/…, .operator const char* 是对String的强制转换,例如调用 .c_str()
-
无论如何都将 .toAscii() 替换为 .toLatin1() ,因为这与准确的名称相同,并考虑移至人们通常希望长期拥有的 .toUtf8() 。 .operator const char*() 可以替换为 .constData(),它在 Qt 中不那么模糊,相当于 .c_str()。
-
与模板生成方式有关?一些实例化模板实例的方法,不能很好地结合在一起。不确定VS。如果您正在调试构建过程,有时清理会清除问题。编译器链接器可以构建特定实例实例化位置的列表,这些列表可能会变得混乱。如果您已经在库中实例化了一个实例,我不确定您如何让链接器/编译器不再创建另一个。您也许可以使用使用弱符号的方法。它会复制实例,但在链接时只使用一个。