I know there are a lot questions here about this topic, but I can't find the unreferenced symbol in my code.
This is the error:
error LNK2019: unresolved external symbol "public: __thiscall MyString::MyString(char const *)" (??0MyString@@QAE@PBD@Z) referenced in function "public: __thiscall Fahrzeug::Fahrzeug(char *)" (??0Fahrzeug@@QAE@PAD@Z)
This is the header for the string class created:
#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
This is the cpp file for mystring class
#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){
//
//}
and here comes the program on which i will use the mystring class
Header:
#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 file:
#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;
//}
main program:
#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;
}
That's a linking error. That means that the compiler could find the prototype of the function but that it couldn't find the function's actual definition.
In your specific case, by creating the kz
variable in the Fahrezug
class, you called the constructor for the MyString
class which for some reason the linker couldn't find the definition of. My guess is that that's because the header for the string class and the source file for the string class are identical so the linker sees the definition of the constructor twice and doesn't know which one to use (even if the two are identical, the linker doesn't check that, when it sees two definitions for the same function, it gives you an error without looking any further).
If you pasted the source instead of the header by accident, maybe the problem is that you forgot to include your source file in the project (the source file needs to be in the list of source files in your IDE).
I also recommend using
#ifndef MYHEADER_H
#define MYHEADER_H
at the beginning of each header file and #endif
at the end to avoid including twice the same header file and therefore getting this type of error.
The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.