C++ already defined in functions.obj

daemon777

Lt. Commander
Dabei seit
Dez. 2003
Beiträge
1.371
Ich habe mal wieder ein Problem.

Und zwar habe ich ein kleines Programm gebastelt welches 1. nicht besonders groß ist und 2. auch funktioniert hat. Allerdings hat da noch alles in einer Datei gestanden. Ich habe einfach nicht erwartet, dass ich noch so viel an diesem Programm rumbasteln werde.

Jedenfalls habe ich mir dann die Arbeit gemacht, dass in mehrere Dateien aufzuspalten. Schön und gut. Allerdings habe ich jetzt eine Fehlermeldung. Dabei habe ich doch eigentlich nichts am Code geändert.

------ Build started: Project: test2, Configuration: Debug Win32 ------
Linking...
laden.obj : error LNK2005: "public: __thiscall CFunctions::CFunctions(void)" (??0CFunctions@@QAE@XZ) already defined in functions.obj
laden.obj : error LNK2005: "public: __thiscall CFunctions::~CFunctions(void)" (??1CFunctions@@QAE@XZ) already defined in functions.obj
laden.obj : error LNK2005: "public: int __thiscall CFunctions::strToint(class std::basic_string<char,struct std::char_traits<char>,class std::allocator<char> >)" (?strToint@CFunctions@@QAEHV?$basic_string@DU?$char_traits@D@std@@V?$allocator@D@2@@std@@@Z) already defined in functions.obj
main.obj : error LNK2005: "public: __thiscall CFunctions::CFunctions(void)" (??0CFunctions@@QAE@XZ) already defined in functions.obj
main.obj : error LNK2005: "public: __thiscall CFunctions::~CFunctions(void)" (??1CFunctions@@QAE@XZ) already defined in functions.obj
main.obj : error LNK2005: "public: int __thiscall CFunctions::strToint(class std::basic_string<char,struct std::char_traits<char>,class std::allocator<char> >)" (?strToint@CFunctions@@QAEHV?$basic_string@DU?$char_traits@D@std@@V?$allocator@D@2@@std@@@Z) already defined in functions.obj
main.obj : error LNK2005: "public: __thiscall CLaden::CLaden(void)" (??0CLaden@@QAE@XZ) already defined in laden.obj
main.obj : error LNK2005: "public: int __thiscall CLaden::readdat(char *)" (?readdat@CLaden@@QAEHPAD@Z) already defined in laden.obj
D:\PFADZUMPROJEKT\test2.exe : fatal error LNK1169: one or more multiply defined symbols found
Build log was saved at "file://d:\PFADZUMPROJEKT\test\test2\test2\Debug\BuildLog.htm"
test2 - 9 error(s), 0 warning(s)
========== Build: 0 succeeded, 1 failed, 0 up-to-date, 0 skipped ==========

Der Quellcode besteht eigentlich nur aus 2 Klassen, die in 2 verschiedenen Dateien liegen und einer main-Datei, die Funktionen dieser Klassen aufruft. Richtig included ist denke ich auch alles, denn ansonsten würde ich ja eine andere Fehlermeldung bekommen.

Könnt ihr mir mal wieder helfen ?

danke schon mal :)
 
Du scheinst die ganzen Methoden:
- CFunctions()
- ~CFunctions()
- usw.

mehrfach definiert zu haben.
Der Compiler sagt dir nun, dass du das nicht machen darfst.

Wenn dir das nicht hilft, dann zeige uns mal den Code der Klassen und deren Header-Dateien.
 
wahrscheinlich includierst du zuviel. ich denke es sollten alle files einzeln übersetzt werden und dann zusammengelinkt werden. anscheinend werden aber in deinem main die anderen files mitübersetzt und beim endgültigen zusammenlinken ist der code dann mehrfach drin.

um sicherzugehn könntes ja mal die includes und die signatur der mehoden in den einzelnen files posten.
 
Hab ich aber (so weit ich weiß) nicht. Als ich alles in einer Datei hatte gings ja auch noch.

In der level.cpp stehen bisher nur grundlegende Includes + "using namespace std;"

functions.cpp
Code:
#ifndef FUNCTIONS_CPP
#define FUNCTIONS_CPP

#include "level.cpp"

class CFunctions
{
public:
	int strToint(string convert);
	CFunctions();
	~CFunctions();
};

CFunctions::CFunctions()
{

}

CFunctions::~CFunctions()
{

}



int CFunctions::strToint(string convert)
{
	int result=0;
	const char * cconvert;
	cconvert=convert.c_str();

	while (*cconvert >= '0' && *cconvert <='9') 
	{
      result = (result * 10) + (*cconvert - '0');
	  cconvert++;
    }

	return result;
}

#endif

laden.cpp
Code:
// Datei um eine Level-Datei einzulesen

#ifndef LADEN_CPP
#define LADEN_CPP

#include "functions.cpp"

using namespace std;

class CLaden
{
private:
	static const int anzcommands=6;

public:
	string commands[anzcommands];

	CLaden();
	~CLaden();
	int getanzcommands() {return anzcommands;}
	int readdat(char * file);
};

CLaden::CLaden()
{
	commands[0]="name:";
	commands[1]="user1:";
	commands[2]="user2:";
	commands[3]="sizex:";
	commands[4]="sizey:";
	commands[5]="field:";
}

CLaden::~CLaden()
{

}

int CLaden::readdat(char * file)
{
	CFunctions mfunctions;
	
	string findstring;
	string subfindstring; // Für den ersten übergebenen Wert
	string subfindstring2; // Für den 2. übergebenen Wert

	string name;
	string user1;
	string user2;

	int sizex;
	int sizey;

	int zaehler=0; //schwachsinn braucht man nicht !
	
	char inp[60];
	ifstream filestream(file);
	if(filestream)
	{
		while(!filestream.eof())
		{
			filestream.getline(inp,60);
			findstring=inp;

			cout<<inp<<endl;
			
			int stelle=0;
			int stelle2=0;
			
			
			for(int i=0;i<getanzcommands();i++)
			{
				stelle=findstring.find(commands[i]);

				if(stelle!=-1)
				{
					cout<<commands[i]<<" wurde entdeckt !"<<endl;
					cout<<"Es wird nun versucht "<<commands[i]<<" auszulesen !"<<endl;
				
					subfindstring=findstring.substr(stelle+commands[i].size(),findstring.size());

					if(i==0) name=subfindstring;
					if(i==1) user1=subfindstring;
					if(i==2) user2=subfindstring;
					if(i==3) sizex=mfunctions.strToint(subfindstring);
					if(i==4) sizey=mfunctions.strToint (subfindstring);
					if(i==5)
					{ 
						cout<<"Jetzt wird ein Field eingelesen ! Das wird hart !"<<endl;
						cout<<"Der gefundene String ist: "<<subfindstring<<endl;		
						
			
						stelle2=subfindstring.find(" ");

						subfindstring2=subfindstring.substr(stelle2+1,subfindstring.size());
						
						cout<<"DEBUG-SIZE: "<<subfindstring2.size()<<endl;
						cout<<"DEBUG-SIZE-STELLE: "<<stelle2<<endl;
						cout<<"stelle+commands[i]: "<<stelle+commands[i].size()<<endl;
						cout<<"subfindstring.size()-(subfindstring2.size()+1)"<<findstring.size()-(subfindstring2.size()+1)<<endl;
						cout<<"subfindstring2: "<<subfindstring2<<endl;
						//Jetzt muss der subfindstring2 in eine var geschrieben werden und ist somit der 2. (!!!) übergebene Wert
						
						subfindstring2=subfindstring.substr(stelle,(subfindstring.size()-(subfindstring2.size()+1)));
						cout<<"subfindstring2: "<<subfindstring2<<endl;
						//Jetzt muss der subfindstring2 in eine var geschrieben werden und ist somit der 1. (!!!) übergebene Wert
						zaehler++;

					}

					cout<<commands[i]<<" ist: "<<subfindstring<<endl;
				}
			}
		}
		cout<<"Die eingelesenen Werte sind:\nname:"<<name<<"\nuser1:"<<user1<<"\nuser2:"<<user2<<"\nsizex:"<<sizex<<"\nsizey:"<<sizey<<endl;
		cout<<"Es wurden "<<zaehler<<" Felder entdeckt !"<<endl;
		return 1;
	}
	else
	{
		return 0;
	}
}
#endif

und die main.cpp
Code:
#include "laden.cpp"

int main()
{
	CLaden mladen;

	cout<<"Dies ist ein Programm das eine Datei oeffnet und ausliest !"<<endl;
	
	if(mladen.readdat("test.txt"))
	{
		cout<<"Lesen erfolgreich !"<<endl;
	}
	else
	{
		cout<<"Die Datei konnte nicht geoeffnet werden !"<<endl;
	}

	system("pause");
	return 0;
}

Manche wissen vielleicht schon, dass ich mich schon seid längerer Zeit mit dem öffnen und auswerten von Dateien rumschlage :evillol:

(Bitte nicht schlagen @Arnd und Th3 N4tz3r. Die elegantere Lösung hab ich nämlich doch nicht zu stande bekommen :D )


Ich bin für jeden Tip, Lösung usw. dankbar. Diesesmal muss es einfach funktionieren.
 
Öhm du solltest dir nochmal über die Trennung in cpp und header-Files klar werden. :)

1. man inkludiert nie nie nie nie nie .cpp-Files.
2. die Deklaration einer Klasse kommt ins .h-File, die Definition ins .cpp-File

Beispiel:

Code:
// Deklaration
class X
{
public:
  void tuwas();
};

// Definition
void X::tuwas()
{
}

Da die Definition bei dir durch das inkludieren von .cpp-Files mehrfach sichtbar ist, gibts die entsprechenden Fehlermeldungen.

Da man übrigens .cpp-Files nie inkludiert, kommen da auch keine Includeguards rein (#ifndef ...).
 
ah es funktioniert :)

Vielen Dank für eure Hilfe.
 
Hallo daemon777,

ich würde manches vielleicht anders machen, aber so im allgemeinen ist Dein Code ganz gut lesbar.
Was sich noch gut machen würde, wären Kommentare was die einzelnen Methoden machen. Z.B. so:

Code:
//////////////////////////////////////////////////////////////////////////////
// Methode:      strToint
// Parameter:    string convert
// Rückgabe:     int 
// Beschreibung: Konvertiert einen String zu einem Integer
//////////////////////////////////////////////////////////////////////////////
int CFunctions::strToint(string convert)
{
...
}

Das ist zwar deutlich mehr Aufwand, lohnt sich aber wenn man den Code später (z.B. in einem Jahr) nochmal anschaut. Oder an andere weitergibt, die damit arbeiten sollen.

MfG

Arnd
 
Zuletzt bearbeitet:
Werbebanner
Zurück
Top