2016-11-23 3 views
0

Ich weiß, es gibt viele Fragen hier zu diesem Thema, aber ich kann nicht das Symbol in meinem Code nicht referenziert finden.Helfer Verständnis Linker Fehler LNK2019

Dies ist der Fehler:

error LNK2019: unresolved external symbol "public: __thiscall MyString::MyString(char const *)" ([email protected]@[email protected]@Z) referenced in function "public: __thiscall Fahrzeug::Fahrzeug(char *)" ([email protected]@[email protected]@Z)

Dies ist der Header für die String-Klasse erstellt:

#ifndef MyString_h 
#define MyString_h 

#include <ostream> 

using namespace std; 


class MyString{ 

    char *strPtr=nullptr; 
    unsigned int strSize; 
    unsigned int strCapacity; 
public: 
    //Standardkonstruktor 
    MyString(); 
    //Konvertierkonstruktor 
    MyString(const char *); 
    //Kopierkonstruktor 
    MyString(const MyString&); 
    //Destruktor 
    ~MyString(); 


    void reserve(unsigned int c); 
    MyString & append(MyString &); 
    MyString & assign(MyString &); 

    unsigned int size(); 
    unsigned int capacity(); 
    void clear(); 
    bool empty(); 
    const char* c_str(); 

    char &at(int); 

    MyString operator+(MyString &); 
    bool operator==(const MyString &); 
    MyString operator=(MyString &); 
    friend ostream & operator<<(ostream &, MyString); 
}; 

//MyString operator+(const MyString &); 
//MyString operator==(const MyString &, const MyString &); 
//MyString operator[](MyString &); 
//MyString operator<<(const MyString &); 

#endif 

Dies ist die CPP-Datei für mystring Klasse

#include "MyString.hpp" 
    #include <ostream> 
    using namespace std; 
    #include <cstring> 



    //Hausaufgabe 2 Eigene String Klasse Teil 1 

    //Standardkonstruktor legt leeren String an 
    MyString::MyString() 
    :strCapacity(1), strSize(0) 
    { 

     this->strPtr = new char[strCapacity]; 
     /*this->strPtr[0] = "\0";*/ 
    } 


    // Konvertierkonstruktor wandelt C-String in MyString um 
    MyString::MyString(const char * string){ 

     //größe String herausfinden 
     unsigned int i = strlen(string); 
     //Größe und Kapazität des Strings festlegen 
     this->strCapacity = i; 
     this->strSize = i; 
     // Dynamisches Array Erzeugen. i+1 für abschließendes "\0" Zeichen 
     this->strPtr = new char[i+1]; 
     //string in strPtr kopieren 
     strncpy(this->strPtr, string, i); 

     //Abschließendes "\0" Zeichen einfügen 
     this->strPtr[i] = '\0'; 
    } 

    MyString::MyString(const MyString & old){ 
     //Tiefe Kopie von old anlegen 
     int size = int(strlen(old.strPtr)); 
     strPtr = new char[size]; 
     strncpy(strPtr, old.strPtr, old.strSize); 
     this->strSize = int(strlen(old.strPtr)); 
     this->strCapacity = old.strCapacity; 
     this->strPtr[this->strSize] = '\0'; 
    } 

    MyString::~MyString(){ 
     // Freigegebener Speicher wird wieder gelöscht 
     delete[] this->strPtr; 
     strPtr = nullptr; 
    } 

    void MyString::reserve(unsigned int c){ 
     //prüfen ob Speicherplatz benötigt wird 

      //reservespeicher wird angelegt und String wird gesichert 
      char *temp = new char[this->strSize]; 
      strncpy(temp,this->strPtr,this->strSize) ; 
      //Destruktor zum löschen des freigegebenen Speichers wird aufgerufen 
      delete[] strPtr; 
      //Speicher mit erhöhter Kapazität wird angefordert 
      this->strPtr = new char[sizeof(char)*(c+1)]; 
      //Gesicherter String auf neuen Speicher übertragen und "\0" wird eingefügt 
      strncpy(this->strPtr, temp, this->strSize); 
      /*this->strPtr[c+1] = '\0';*/ 
      //temp wird wieder gelöscht 
      delete[] temp; 

    } 
    //Gibt den C-String zurück 
    const char* MyString::c_str(){ 

     return strPtr; 
    } 
    //gibt größe des Strings ohne abhließendes 0-Zeichen zurück 
    unsigned int MyString::size(){ 
     return this->strSize; 

    } 
    //Leert den String 
    void MyString::clear(){ 
     for (int i = 0; i < this->strCapacity; i++) { 
      this->strPtr[i] = 0; 
     } 

    } 
    //Hängt Strings aneinander 
    MyString & MyString::append(MyString &str){ 
     // Ermittelt Größe des neuen Strings 
     unsigned int newSize = this->strSize+str.strSize; 
     //Größe und Kapazität des Strings werden aktualisiert 
     this->strSize = newSize; 
     this->strCapacity = newSize; 
     //vergrößert den Speicher für den neuen String 
     this->reserve(newSize); 
     //Fügt die Strings zusammen 
     strcat(this->strPtr,str.strPtr); 
     //abschließendes 0-Zeichen 
     this->strPtr[this->strSize] = '\0'; 
     return str; 
    } 
    //Überschreibt String mit neuen Chars 
    MyString & MyString::assign(MyString &str){ 
     //prüft ob neuer Speicher beschafft werden soll 
     if (this->strSize < str.strSize){ 
      reserve(str.strSize); 
      //fügt neuen String ein 
      strncpy(this->strPtr, str.strPtr,str.strSize); 
      //aktualisiert Größe und Kapazität des Strings 
      this->strSize = str.size(); 
      this->strCapacity = str.capacity(); 
      //abschließendes 0-Zeichen 
      this->strPtr[this->strSize] = '\0'; 
     } 
     else{ 
      //falls Speicher nicht vergrößert werden muss 
      //wird string eingefügt 
      strncpy(this->strPtr, str.strPtr, str.strSize); 
     } 
     return str; 
    } 
    //Gibt Kapazität zurück 
    unsigned int MyString::capacity(){ 
     return this->strCapacity; 
    } 
    //prüft ob String leer ist 
    bool MyString::empty(){ 
     if (this->strSize = 0) 
      return true; 
    } 
    //ersetzt Zeichen an der i-ten Stelle 
    char &MyString::at(int i){ 
     if (i > this->strCapacity) 
      return this->strPtr[0]; 
     else{ 
      return this->strPtr[i-1]; 
     } 
    } 

    //Hausaufgabe 3 Eigene String Klasse Teil 2 Operatoren 

    MyString MyString::operator+(MyString & other){ 

     MyString neu(this->strPtr); 

     neu.append(other); 
     return neu; 
    } 
    bool MyString::operator==(const MyString & compare){ 
     if (this->strSize == compare.strSize){ 
      for (int i = 0; (this->strPtr[i] && compare.strPtr[i]) != '\0'; i++){ 
       if (this->strPtr[i] != compare.strPtr[i]){ 
        return 0; 
        break; 
       } 
       else return 1; 


      } 

     } 

    } 
    ostream &operator<< (ostream & push, MyString out){ 
     /*for (int i = 0; out.strPtr[i] != '\0'; i++){ 
      push << out.strPtr[i]; 
     }*/ 

     push << out.c_str(); 
     return push; 

    } 

    MyString MyString::operator=(MyString & change){ 


     this->assign(change); 
     return change; 
    } 

    //MyString MyString::operator[](MyString & index){ 
    // 
    //} 

und hier kommt das Programm, auf dem ich die MyString-Klasse

verwenden werde 10

Rubrik:

#include"..\A3\A3\MyString.hpp" 
#pragma once 
class Fahrzeug{ 

private: 
    MyString kz; 
    /*static int vin;*/ 
    double km; 
public: 
    Fahrzeug(char *kfz); 
    void fahren(double); 
    /*friend ostream & operator<<(ostream &, Fahrzeug);*/ 
}; 

CPP-Datei:

#include "Fahrzeug.hpp" 
#include"..\A3\A3\MyString.hpp" 
#pragma once 

Fahrzeug::Fahrzeug(char* kfz) 
:kz(kfz) 
{ 

} 

void Fahrzeug::fahren(double km) 
{ 

    this->km += km; 
} 
//ostream &operator<<(ostream& push, Fahrzeug out){ 
// return push<<"KennZeichen: "<<out.kz<<endl<<"VIN: "/*<<out.vin*/<<endl<<"KM: "<<out.km<<endl; 
//} 

Hauptprogramm:

#include "Fahrzeug.hpp" 

#pragma once 
#include <iostream> 
using namespace std; 

//int Fahrzeug::zaehler = 0; 

int main() { 
    Fahrzeug f1("ES - H 123"); 
    /*cout << f1 << endl;*/ 
    f1.fahren(101.5); 
    /*cout << f1 << endl;*/ 
    Fahrzeug f2("ES - M 4711"); 
    f2.fahren(10.57); 
    /*cout << f2 << endl;*/ 
    return 0; 
} 
+3

Bitte zeigen Sie uns den Header Ihrer 'MyString' Klasse (Deklaration davon). Der Code, den Sie als _header_-Datei beschrieben haben, ist ** identisch mit dem, den Sie als _.cpp_-Datei beschrieben haben. –

+0

Ich vermute, dass der Linker die Objektdatei für MyString nicht sehen kann. Überprüfen Sie den Buildbefehl/das Skript, um sicherzustellen, dass die MyString.obj in den Linkbefehl aufgenommen wird. Beachten Sie außerdem, dass Sie die .cpp-Datei für MyString zweimal eingefügt haben - einmal anstelle der MyString-Kopfzeile. –

+0

Sie sollten in den CPP-Dateien wahrscheinlich nicht "# Pragma einmal" haben, aber das ist nicht, was dieses Problem verursacht. –

Antwort

0

, dass ein Verknüpfungsfehler ist. Das bedeutet, dass der Compiler den Prototyp der Funktion finden konnte, aber die tatsächliche Definition der Funktion nicht finden konnte.

In Ihrem speziellen Fall durch die kz Variable in der Fahrezug Klasse erstellen, genannt Sie den Konstruktor für die MyString Klasse, die der Linker aus irgendeinem Grunde nicht die Definition finden. Meine Annahme ist, dass der Header für die String-Klasse und die Quelldatei für die String-Klasse identisch sind, so dass der Linker die Definition des Konstruktors zweimal sieht und nicht weiß, welche zu verwenden ist (auch wenn beide identisch sind) Linker prüft nicht, ob es zwei Fehler gibt, wenn es zwei Definitionen für die gleiche Funktion sieht, ohne weiter zu suchen.

Wenn Sie versehentlich die Quelle anstelle des Headers eingefügt haben, besteht das Problem möglicherweise darin, dass Sie Ihre Quelldatei in das Projekt eingefügt haben (die Quelldatei muss in der Liste der Quelldateien in der IDE enthalten sein).

auch

#ifndef MYHEADER_H 
#define MYHEADER_H 

am Anfang jeder Header-Datei und #endif am Ende mit Ich empfehle einschließlich zweimal die gleiche Header-Datei zu vermeiden und damit diese Art von Fehlern.

+1

Ich glaube nicht, dass der Header und die Quelldatei für MyString identisch sind. Ich denke der OP hat den Header versehentlich anstelle der Quelle eingefügt. Sie haben Recht, wenn Sie dies einen Linker-Fehler nennen, aber dann sprechen Sie über den Compiler anstelle des Linkers. –