2016-11-23 8 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){ 
    // 
    //} 

とここにあります私がミストリングクラスを使用するプログラムが来る

ヘッダー:

#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がlinkコマンドに含まれていることを確認します。また、MyStringヘッダーの代わりに、MyStringの.cppに2回ペーストしたように見えることにも注意してください。 –

+0

.cppファイルに '#pragma once'を入れてはいけませんが、これはこの問題の原因ではありません。 –

答えて

0

リンクエラーです。つまり、コンパイラは関数のプロトタイプを見つけることができますが、関数の実際の定義を見つけることはできませんでした。

具体的には、Fahrezugクラスにkz変数を作成すると、MyStringクラスのコンストラクタが呼び出され、何らかの理由でリンカが定義を見つけることができませんでした。私の推測は、文字列クラスのヘッダーと文字列クラスのソースファイルは同じなので、リンカーはコンストラクターの定義を2回見て、どちらを使用するかはわからないからです。リンカは、同じ関数の2つの定義を見ると、それ以上は何も見ずにエラーを出します)をチェックしません。

ヘッダーの代わりに偶然にソースを貼り付けた場合は、ソースファイルをプロジェクトに含めるのを忘れていることが考えられます(ソースファイルはIDEのソースファイルのリストにある必要があります)。

私も二度同じヘッダファイルを含むため、この種の誤りを避けるために最後に、各ヘッダファイルと#endifの先頭に

#ifndef MYHEADER_H 
#define MYHEADER_H 

を使用することをお勧めします。

+1

MyStringのヘッダとソースファイルが同じではないと思います。私はOPがソースの代わりに偶然ヘッダーを貼り付けたと思う。あなたはこれをリンカエラーと呼びますが、リンカの代わりにコンパイラについて話します。 –

関連する問題