我从Qt开始,现在我遇到了这个错误:
Lwt
main.cpp中:
duplicate symbol _t in:
main.o
handler.o
duplicate symbol _mp in:
main.o
handler.o
duplicate symbol _l in:
main.o
handler.o
duplicate symbol _ti in:
main.o
handler.o
ld: 4
duplicate symbols for architecture x86_64 clang: error: linker command failed with exit code 1 (use -v to see invocation)
handler.cpp:
#include "handler.h"
int main(int argc, char **argv)
{
QFile *file = new QFile(":/xml/example.tmx");
QXmlSimpleReader xmlReader;
QXmlInputSource *source = new QXmlInputSource(file);
Handler *handler = new Handler;
xmlReader.setContentHandler(handler);
xmlReader.setErrorHandler(handler);
bool ok = xmlReader.parse(source);
if (!ok)
std::cout << "Parsing failed." << std::endl;
else {
QStringList names = handler->names();
QStringList attributes = handler->attributes();
QStringList attributeName = handler->attributeName();
QList<int> indentations = handler->indentations();
QList<int> anzahl = handler->anzahl();
int items = names.count();
int durchgang = 0;
for (int i = 0; i < items; ++i) {
for (int j = 0; j < indentations[i]; ++j){
std::cout << " ";
}
std::cout << names[i].toLocal8Bit().constData() << " " ;
//weitere attribute printen(so viele wie vorhanden
for(int y = 0; y < anzahl[i] ; y++){
std::cout << attributeName[durchgang].toLocal8Bit().constData() << " = "<< attributes[durchgang].toLocal8Bit().constData() << " ";
durchgang++;
}
std::cout << std::endl;
}
imageloader il;
QStringList sources;
for(int x = 0; x < mp.tilesets.length();x++){
sources.append(mp.tilesets[x].source);
}
QList <QImage> images;
images = il.Loadtilesets(mp.tilesets.length(),sources);
}
std::cout << "Beendet"<<std::endl;
return 0;
}
handler.h中:
#include "handler.h"
/*!
Reset the state of the handler to ensure that new documents are
read correctly.
We return true to indicate that parsing should continue.
*/
bool Handler::startDocument()
{
elementName.clear();
elementAttributes.clear();
elementIndentation.clear();
elementAnzahl.clear();
elementAttributeName.clear();
indentationLevel = 0;
return true;
}
/*!
Process each starting element in the XML document.
Append the element name to the list of elements found; add its
corresponding indentation level to the list of indentation levels.
Increase the level of indentation by one column.
We return true to indicate that parsing should continue.
*/
bool Handler::startElement(const QString &, const QString &,
const QString & qName, const QXmlAttributes & atts)
{
elementName.append(qName);
int anzahl = 0;
for(int index = 0; index < atts.length();index++){
int d = index;
if(qName == "map"){//alle attribute von map
if(atts.qName(index) == "width"){
mp.width = atts.value(index).toInt();
index ++;
}
if(atts.qName(index)== "height"){
mp.height = atts.value(index).toInt();
index++;
}
}
if(qName == "tileset"){
tileset t;
if(atts.qName(index)=="firstgid"){
t.firstgid = atts.value(index).toInt();
index++;
}
if(atts.qName(index)=="name"){
t.name = atts.value(index);
index ++;
}
if(atts.qName(index)=="tilewidth"){
t.tilewidth = atts.value(index).toInt();
index++;
}
if(atts.qName(index)=="tileheight"){
t.tileheight = atts.value(index).toInt();
index++;
}
if(atts.qName(index)=="tilecount"){
t.tilecount = atts.value(index).toInt();
index++;
}
if(atts.qName(index)=="columns"){
t.columns = atts.value(index).toInt();
index++;
}
}
if(qName == "image"){//!muss noch ein try catch block einbauen fals ein image nicht hinter einem tileset ist
if(atts.qName(index) == "source"){
t.source = atts.qName(index);
mp.tilesets.append(t);
}
}
if(qName =="layer"){
if(atts.qName(index)=="name"){
l.name = atts.qName(index);
index++;
}
if(atts.qName(index)=="width"){
l.width = atts.qName(index).toInt();
index++;
}
if(atts.qName(index)=="height"){
l.height= atts.qName(index).toInt();
index++;
}
}
if(qName == "data"){
for(int x = 0; x< l.height*l.width; x++){
if(atts.qName(index)=="gid"){
ti.gid = atts.value(index).toInt();
l.tiles.append(ti);
index++;
}
}
mp.layers.append(l);
}
index = d;//für das auslesen und couten
elementAttributes.append(atts.value(index));
elementAttributeName.append(atts.qName(index));
anzahl = index+1;
}
elementAnzahl.append(anzahl);
elementIndentation.append(indentationLevel);
indentationLevel += 1;
return true;
}
/*!
Process each ending element in the XML document.
Decrease the level of indentation by one column.
We return true to indicate that parsing should continue.
*/
bool Handler::endElement(const QString &, const QString &,
const QString &)
{
indentationLevel -= 1;
return true;
}
/*!
Report a fatal parsing error, and return false to indicate to the reader
that parsing should stop.
*/
bool Handler::fatalError (const QXmlParseException & exception)
{
qWarning() << QString("Fatal error on line %1, column %2: %3").arg(
exception.lineNumber()).arg(exception.columnNumber()).arg(
exception.message());
return false;
}
/*!
Return the list of element names found.
*/
QStringList& Handler::names ()
{
return elementName;
}
QList<int>& Handler::indentations ()
{
return elementIndentation;
}
QStringList& Handler::attributes ()
{
return elementAttributes;
}
QList<int>& Handler::anzahl (){
return elementAnzahl;
}
QStringList& Handler::attributeName (){
return elementAttributeName;
}
答案 0 :(得分:0)
你似乎在.h文件中有全局变量定义,如果.h文件包含在许多.cpp文件中,这将无效(这基本上是.h文件的目的,所以...)。
要正确地执行此操作,您应该在.h文件中包含类似声明的内容:
extern int t;
然后在一个 .cpp文件中,在顶层(不在函数内),你应该有实际的定义:
int t;
第一行告诉编译器某处有int t
个全局变量,所以它只是使用它并信任链接器来找到它。然后,当链接器查找该符号时,它必须找到其中一个符号,否则它会抱怨重复的符号,或者没有找到符号。
我不会更深入地了解这个(hows或者为什么),但这是C ++ 和 Qt,所以你基本上应该完全避免像这样的全局变量(它们已经足够糟糕了) C,但你有更少的选择)。既然你正在学习,你不需要强调它,现在只需使用它们,但请记住,你应该学会做事的方法,这样你就不需要它们了。