2016-11-23 111 views
0

我知道這裏有很多關於這個主題的問題,但是我找不到我的代碼中未引用的符號。幫助者瞭解鏈接錯誤LNK2019

這是錯誤:

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)

這是創建的字符串類的頭:

#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 

這是在MyString類cpp文件

#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){ 
    // 
    //} 

這裏來的程序上我將使用mystring類

頁眉:

#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文件:

#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; 
//} 

主程序:

#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

請向我們展示您的MyString類的頭(聲明它)。您描述爲_header_文件的代碼與您描述爲_.cpp_文件的代碼相同**。 –

+0

我懷疑鏈接器沒有看到MyString的目標文件。檢查您的構建命令/腳本以確保MyString.obj包含在鏈接命令中。另外請注意,您似乎已經粘貼了兩次.cpp MyString - 一次代替MyString頭。 –

+0

你可能不應該在.cpp文件中有'#pragma once',但這不是導致這個問題的原因。 –

回答

0

這是一個鏈接錯誤。這意味着編譯器可以找到該函數的原型,但它找不到該函數的實際定義。

在您的具體情況下,通過在Fahrezug類中創建kz變量,您調用了MyString類的構造函數,由於某些原因,鏈接程序找不到定義。我的猜測是,這是因爲字符串類的頭部和字符串類的源文件是相同的,所以鏈接器看到構造函數的定義兩次,並且不知道要使用哪一個(即使兩者是相同的,鏈接器不檢查,當它看到相同函數的兩個定義時,它會給你一個錯誤而不會再看)。

如果您錯誤地粘貼了源代碼而不是標頭,可能問題是您忘記將源文件包含在項目中(源文件需要位於IDE中的源文件列表中)。

我還建議使用

#ifndef MYHEADER_H 
#define MYHEADER_H 

在每個頭文件和#endif的開始處結束,以避免兩次包括相同的頭文件,並因此獲得此類型的錯誤。

+1

我不認爲MyString的頭文件和源文件是相同的。我認爲OP不小心將報頭粘貼在報頭上,而不是來源。你正確地調用了這個鏈接器錯誤,但是接下來你將討論編譯器而不是鏈接器。 –