[英]Helper understanding linker error LNK2019
我知道这里有很多与此主题有关的问题,但是我在代码中找不到未引用的符号。
这是错误:
错误LNK2019:未解析的外部符号“ public:__thiscall MyString :: MyString(char const *)”(?? 0MyString @@ QAE @ PBD @ Z)在函数“ public:__thiscall Fahrzeug :: Fahrzeug(char *)”中引用(? 0Fahrzeug @@ QAE @ PAD @ 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;
}
那是链接错误。 这意味着编译器可以找到该函数的原型,但是找不到该函数的实际定义。
在您的特定情况下,通过在Fahrezug
类中创建kz
变量,您调用了MyString
类的构造函数,由于某种原因,链接器找不到该构造函数的定义。 我的猜测是,这是因为字符串类的标头和字符串类的源文件是相同的,所以链接器会两次看到构造函数的定义,并且不知道使用哪个(即使两者相同,链接器不会检查它,当看到相同功能的两个定义时,它会给您一个错误,而无需进一步检查。
如果您偶然粘贴了源代码而不是标题,则可能是因为您忘记了将源文件包含在项目中(源文件必须位于IDE中的源文件列表中)。
我也建议使用
#ifndef MYHEADER_H
#define MYHEADER_H
在每个头文件的开头和#endif
的末尾,以避免两次包含相同的头文件,因此会出现这种类型的错误。
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.