I have this abstract class
class ImageIO {
protected:
ImageIO() {}
public:
virtual bool load(const std::string & filename, const std::string & format) = 0;
virtual bool save(const std::string & filename, const std::string & format) = 0;
}
And the implementation
class Image : public Array2D<Color>, public ImageIO {
private:
static int case_insensitive(string s) {
transform(s.begin(), s.end(), s.begin(), tolower);
if (s.compare("ppm") == 0) {
return 1;
}
return 0;
}
public:
bool load(const std::string& filename, const std::string& format) {
if (case_insensitive(format)) {
float* data = ReadPPM(filename.c_str(), (int*)width, (int*)height);
for (int i = 0, j = 0; i < width * height; i++, j += 3) {
buffer[i] = Color(data[j], data[j + 1], data[j + 2]);
}
delete[] data;
return true;
}
return false;
}
bool save(const std::string& filename, const std::string& format) {
if (case_insensitive(format)) {
float* data = new float[width * height * 3];
for (int i = 0, j = 0; i < width * height; i++, j += 3) {
data[j] = buffer[i].x;
data[j + 1] = buffer[i].y;
data[j + 2] = buffer[i].z;
}
bool write_check = WritePPM(data, width, height, filename.c_str());
delete[] data;
return write_check;
}
return false;
}
};
And I keep getting an abstract class cannot be instantiated error if I try this
Image test = Image();
in my main.
I've also tried declaring t=those two methods in a header file
class Image : public Array2D<Color>, public ImageIO {
private:
static int case_insensitive(std::string);
public:
bool ImageIO::load(const std::string& filename, const std::string& format);
bool ImageIO::save(const std::string& filename, const std::string& format);
};
but then I get unresolved external symbol errors. Is there a problem in the way I'm implementing the two functions or in how my declaring the class?
EDIT: If I declare those two methods in the header file then the error is:
error LNK2019: unresolved external symbol "public: virtual bool __thiscall image::Image::[image::ImageIO]::load(class std::basic_string<char,struct std::char_traits<char>,class std::allocator<char> > const &,class std::basic_string<char,struct std::char_traits<char>,class std::allocator<char> > const &)" (?load#?QImageIO#image##Image#2#UAE_NABV?$basic_string#DU?$char_traits#D#std##V?$allocator#D#2##std##0#Z) referenced in function _main
error LNK2019: unresolved external symbol "public: virtual bool __thiscall image::Image::[image::ImageIO]::save(class std::basic_string<char,struct std::char_traits<char>,class std::allocator<char> > const &,class std::basic_string<char,struct std::char_traits<char>,class std::allocator<char> > const &)" (?save#?QImageIO#image##Image#2#UAE_NABV?$basic_string#DU?$char_traits#D#std##V?$allocator#D#2##std##0#Z) referenced in function _main
If I don't the error is
error C2259: 'image::Image': cannot instantiate abstract class
I also added override and nothing changes.
To specifically answer the question about unresolved external symbols, you don't need the ImageIO parent specifier on the save/load functions. You are declaring that Image itself has those functions, which override the abstract functions on the parent. You will then need to specify Image when implementing them in the cpp file.
Image.hpp
class Image : public Array2D<Color>, public ImageIO {
private:
static int case_insensitive(std::string);
public:
bool load(const std::string& filename, const std::string& format) override;
bool save(const std::string& filename, const std::string& format) override;
};
Image.cpp
bool Image::load(const std::string& filename, const std::string& format) {
if (case_insensitive(format)) {
//etc.
}
return false;
}
bool Image::save(const std::string& filename, const std::string& format) {
if (case_insensitive(format)) {
//etc.
}
return false;
}
Related
This question already has answers here:
What is an undefined reference/unresolved external symbol error and how do I fix it?
(39 answers)
Closed 5 years ago.
#include <iostream>
#include <map>
#include <string>
#include <cstdlib>
using namespace std;
class Shape
{
public :
virtual void draw()=0;
virtual ~Shape(){}
};
class Circle : public Shape
{
string color;
int x;
int y;
int radius;
public:
Circle(string color){
color = color;
}
void setX(int x) {
x = x;
}
void setY(int y) {
y = y;
}
void setRadius(int radius) {
radius = radius;
}
void draw() {
cout << "color :" << color << x << y ;
}
};
class ShapeFactory {
public:
static map<string, Shape*> circlemap;
static Shape* getcircle(string color)
{
Shape *mcircle;
mcircle = circlemap.find(color)->second;
if(mcircle == nullptr) {
mcircle = new Circle(color);
circlemap[color] = mcircle;
// circlemap.insert(std::make_pair(color,mcircle));
}
return mcircle;
}
};
class Flyweightpattern
{
public:
static string getRandomColor(string colors[]) {
int m_rand = rand() % 5;
return colors[m_rand];
}
static int getRandomX() {
return (int)(rand() % 100);
}
static int getRandomY() {
return (int)(rand() % 100);
}
};
int main()
{
string colors[] = { "Red", "Green", "Blue", "White", "Black" };
for(int i=0; i < 20; ++i) {
Circle *circle = dynamic_cast<Circle *>(ShapeFactory::getcircle(Flyweightpattern::getRandomColor(colors)));
circle->setX(Flyweightpattern::getRandomX());
circle->setY(Flyweightpattern::getRandomY());
circle->setRadius(100);
circle->draw();
}
getchar();
return 0;
}
I am getting the linking error during run is below :
flyweight_pattern.obj : error LNK2001: unresolved external symbol
"public: static class std::map,class std::allocator >,class Circle
*,struct std::less,class std::allocator > >,class
std::allocator,class std::allocator > const ,class
Circle *> > > ShapeFactory::circlemap"
(?circlemap#ShapeFactory##2V?$map#V?$basic_string#DU?$char_traits#D#std##V?$allocator#D#2##std##PAVCircle##U?$less#V?$basic_string#DU?$char_traits#D#std##V?$allocator#D#2##std###2#V?$allocator#U?$pair#$$CBV?$basic_string#DU?$char_traits#D#std##V?$allocator#D#2##std##PAVCircle###std###2##std##A)
I have a map in the ShapeFactory class and tried to creating filling the map in the class itself but still not able to resolve the problem.
You didn't defined circlemap, it's a static member, so you should define it (and initialize) in global scope:
map<string, Shape*> ShapeFactory::circlemap = {};
Integral nonvolatile static members can be initialized in class.
Oh, and it is not recommended to do using namespace std; in global scope, that leads to side effects.
You can write something like
using std::map;
to target selected id (map in this case), and you can write using in namespace that contains usage.
I'm getting strange linking error in the main window. I also included the header files of those classes in main window. but still it can't link the virtual functions.
I'm using the following code that is in main:
S3W::IFields *recordsTx = pConnection->GetTransmittedFields();
FieldsDataList *derived = dynamic_cast<FieldsDataList*>(recordsTx);
for (int j = 0; j < 2; j++)
{
VarField& record = derived->CreateDataItem();
FieldsDataList *fields = record.getChildrenDataList();
VarField& fieldGeom1 = fields->CreateDataItem();
fieldGeom1.SetKey("geom");
double x = 47;
double y = 16;
fieldGeom1 = VarField::fromGPS(new ImplGps(x, y));
}
I'm getting the following link Error:
3>MainWindow.obj : error LNK2001: unresolved external symbol "public: virtual struct S3W::IFields & __thiscall VarField::getChildern(void)" (?getChildern#VarField##UAEAAUIFields#S3W##XZ)
3>MainWindow.obj : error LNK2001: unresolved external symbol "public: virtual struct FieldsDataList * __thiscall VarField::getChildrenDataList(void)"
Here is the class definition of the Classes:
// pseudo code
class VarField : public S3W::IField
{
virtual S3W::IFields& getChildern() override;
// Inherited via IField
virtual FieldsDataList * getChildrenDataList() override;
}
and IField is :
struct FieldsDataList;
namespace S3W
{
struct IFields;
struct IField : S3W::IListItem
{
enum class Type { NONE = 0, UINT = 1, DOUBLE = 2, STRING = 3 , GEOM = 4};
virtual S3W::IGps* getGeom() = 0;
virtual double getDouble() const = 0;
virtual unsigned int getUint() const = 0;
virtual const char* getString() const = 0;
virtual const char* getKey() const = 0;
virtual Type getType() const = 0;
virtual ~IField() { }
IField() {}
virtual IFields& getChildern()= 0;
virtual FieldsDataList* getChildrenDataList() = 0;
};
My program compiles, but I get the following link errors:
1>desalter.obj : error LNK2020: unresolved token (0A000065) "private: static double (* DataBace::Number_d_save)[110]" (?Number_d_save#DataBace##$$Q0PAY0GO#NA)
1>desalter.obj : error LNK2020: unresolved token (0A000066) "private: static double (* DataBace::Flow_spec)[5]" (?Flow_spec#DataBace##$$Q0PAY04NA)
1>desalter.obj : error LNK2020: unresolved token (0A000068) "private: static class std::basic_string<char,struct std::char_traits<char>,class std::allocator<char> > * DataBace::Flow_Name" (?Flow_Name#DataBace##$$Q0PAV?$basic_string#DU?$char_traits#D#std##V?$allocator#D#2##std##A)
1>desalter.obj : error LNK2001: unresolved external symbol "private: static double (* DataBace::Flow_spec)[5]" (?Flow_spec#DataBace##$$Q0PAY04NA)
1>desalter.obj : error LNK2001: unresolved external symbol "private: static double (* DataBace::Number_d_save)[110]" (?Number_d_save#DataBace##$$Q0PAY0GO#NA)
1>desalter.obj : error LNK2001: unresolved external symbol "private: static class std::basic_string<char,struct std::char_traits<char>,class std::allocator<char> > * DataBace::Flow_Name" (?Flow_Name#DataBace##$$Q0PAV?$basic_string#DU?$char_traits#D#std##V?$allocator#D#2##std##A)
1>C:\Users\Mojtaba Mohayeji\Documents\Visual Studio 2010\Projects\desalter\Debug\desalter.exe : fatal error LNK1120: 6 unresolved externals
Code:
class DataBace
{
public:
//---
void fLOW_NAME(int indicator, string flow_name)
{
Flow_Name[indicator] = flow_name;
}
string** fLOW_NAME_READ()
{
string** flow_name_read = new string*[1];
for (int i = 1; i < 100; i++)
{
string a = Flow_Name[i];
flow_name_read[i] = &a;
}
return flow_name_read;
}
int Show(string show)
{
for (int i = 0; i < 100; i++)
{
string sh = Flow_Name[i];
if (sh==show)
{
return i;
}
}
}
void FLOW_SPEC(int indicator, double flow_spec[1][5])
{
for (int i = 0; i < 5; i++)
{
Flow_spec[indicator][i] = flow_spec[1][i];
}
}
double** FLOW_SPEC_READ(int SHOW)
{
double** flow_spec_read = new double*[5];
for (int i = 1; i < 5; i++)
{
double a = Flow_spec[SHOW][i];
flow_spec_read[i] = &a;
}
return flow_spec_read;
}
void Number_d_SAVE(int indicator, double Number_d[110])
{
for (int i = 0; i < 110; i++)
{
Number_d_save[indicator][i] = Number_d[i];
}
}
double** Number_d_READ(int SHOW)
{
double** Number_d_read = new double*[110];
for (int i = 1; i < 110; i++)
{
double a = Number_d_save[SHOW][i];
Number_d_read[i] = &a;
}
return Number_d_read;
}
private:
static string Flow_Name[100];
static double Flow_spec[100][5];
static double Number_d_save[100][110];
};
Let's take this snippet code :
class MyClass
{
public:
int m_num;
MyClass(int n) { m_num = n;}
}
If I create an object of this class the following way :
MyClass mc1(5);
MyClass mc2(mc1);
This calls to the default copy-constructor and it'll automatically assign mc2.m_num = mc1.m_num ?
Also if there's a call inside the class which makes an instance the following way :
MyClass mc3(*this);
This will call to the default copy-constructor same as with mc2 the *this is just getting the object itself to be copied ?
Second problem I'm having is with compiling my code with Microsoft Visual Studio 2013.
I've made a String class and when I try to compile I get lot's of linking error telling me that the functions are already defined for some reason.
String.h :
#pragma once
class String
{
private:
char* m_szStr;
unsigned int m_length;
public:
String(const char*);
explicit String(unsigned int);
String(const String&);
~String();
String& operator=(const String&);
bool operator==(const String&) const;
String operator+(const String&) const;
operator const char*() const;
int findStr(char*) const;
int getLen() const;
void copyStr(const char*);
};
String.cpp:
#include "stdafx.h"
#include "String.h"
String::String(const char* pch)
{
m_szStr = NULL;
copyStr(pch);
}
String::String(unsigned int len)
{
m_length = len;
m_szStr = new char[m_length];
}
String::String(const String& that)
{
copyStr(that.m_szStr);
}
String::~String()
{
delete[] m_szStr;
}
String& String::operator=(const String& that)
{
copyStr(that.m_szStr);
return *this;
}
bool String::operator==(const String& that) const
{
if (m_length != that.m_length)
return false;
for (unsigned int i = 0; i < m_length; i++)
{
if (m_szStr[i] != that.m_szStr[i])
return false;
}
return true;
}
String String::operator+(const String& that) const
{
String temp(m_length + that.m_length - 1);
unsigned int offset = m_length;
for (unsigned int i = 0; i < that.m_length; i++)
{
temp.m_szStr[offset] = that.m_szStr[i];
}
return temp;
}
String::operator const char*() const
{
return m_szStr;
}
int String::findStr(char* pch) const
{
unsigned int offset = 0;
unsigned int strIndex = -1;
for (unsigned int i = 0; m_szStr[i] != NULL && pch[offset] != NULL; i++)
{
if (m_szStr[i] == pch[offset])
{
if (strIndex == -1)
strIndex = i;
offset++;
}
else
{
strIndex = -1;
offset = 0;
}
}
return strIndex;
}
int String::getLen() const
{
unsigned int len = 0;
for (unsigned int i = 0; m_szStr[i] != NULL; i++)
{
len++;
}
return len;
}
void String::copyStr(const char* pch)
{
if (!m_szStr)
delete[] m_szStr;
unsigned int pchLen = 0;
for (unsigned int i = 0; pch[i] != NULL; i++)
{
pchLen++;
}
m_length = pchLen;
m_szStr = new char[m_length];
for (unsigned int i = 0; i < m_length; i++)
{
m_szStr[i] = pch[i];
}
}
Code file:
#include "stdafx.h"
#include <iostream>
#include "String.cpp"
using namespace std;
int _tmain(int argc, _TCHAR* argv[])s
{
String s1("Hi!");
String s2(5);
s2 = "Hello, Hi!";
const char* pch = static_cast<const char*>(s2);
cout << pch << endl;
return 0;
}
errors:
Error 1 error LNK2005: "public: __thiscall String::String(class String const &)" (??0String##QAE#ABV0##Z) already defined in assignment4.obj C:\Users\****\Desktop\C++ Programming\assignment4\assignment4\String.obj assignment4
Error 2 error LNK2005: "public: __thiscall String::String(unsigned int)" (??0String##QAE#I#Z) already defined in assignment4.obj C:\Users\****\Desktop\C++ Programming\assignment4\assignment4\String.obj assignment4
Error 3 error LNK2005: "public: __thiscall String::String(char const *)" (??0String##QAE#PBD#Z) already defined in assignment4.obj C:\Users\****\Desktop\C++ Programming\assignment4\assignment4\String.obj assignment4
Error 4 error LNK2005: "public: __thiscall String::~String(void)" (??1String##QAE#XZ) already defined in assignment4.obj C:\Users\****\Desktop\C++ Programming\assignment4\assignment4\String.obj assignment4
Error 5 error LNK2005: "public: class String & __thiscall String::operator=(class String const &)" (??4String##QAEAAV0#ABV0##Z) already defined in assignment4.obj C:\Users\****\Desktop\C++ Programming\assignment4\assignment4\String.obj assignment4
Error 6 error LNK2005: "public: bool __thiscall String::operator==(class String const &)const " (??8String##QBE_NABV0##Z) already defined in assignment4.obj C:\Users\****\Desktop\C++ Programming\assignment4\assignment4\String.obj assignment4
Error 7 error LNK2005: "public: __thiscall String::operator char const *(void)const " (??BString##QBEPBDXZ) already defined in assignment4.obj C:\Users\****\Desktop\C++ Programming\assignment4\assignment4\String.obj assignment4
Error 8 error LNK2005: "public: class String __thiscall String::operator+(class String const &)const " (??HString##QBE?AV0#ABV0##Z) already defined in assignment4.obj C:\Users\****\Desktop\C++ Programming\assignment4\assignment4\String.obj assignment4
Error 9 error LNK2005: "public: void __thiscall String::copyStr(char const *)" (?copyStr#String##QAEXPBD#Z) already defined in assignment4.obj C:\Users\****\Desktop\C++ Programming\assignment4\assignment4\String.obj assignment4
Error 10 error LNK2005: "public: int __thiscall String::findStr(char *)const " (?findStr#String##QBEHPAD#Z) already defined in assignment4.obj C:\Users\****\Desktop\C++ Programming\assignment4\assignment4\String.obj assignment4
Error 11 error LNK2005: "public: int __thiscall String::getLen(void)const " (?getLen#String##QBEHXZ) already defined in assignment4.obj C:\Users\****\Desktop\C++ Programming\assignment4\assignment4\String.obj assignment4
Error 12 error LNK1169: one or more multiply defined symbols found C:\Users\****\Desktop\C++ Programming\assignment4\Debug\assignment4.exe 1 1 assignment4
In your main code file, write:
#include "String.h" // with .cpp you redefine everything !!
Currently you include String.cpp. So in your main file you will redefine everything you have already defined in String.cpp. It will compile, but the linker will be confused because he will find a definition for your String member functions in String.obj as well as in main.obj ("one definition rule").
And you already answerd yourself your copy constructor question
I'm getting an unresolved external error but I can't figure out exactly what's causing it.
error LNK2019: unresolved external symbol "public: __thiscall ABC::ABC(class ABC const &)" (??0ABC##QAE#ABV0##Z) referenced in function "public: __thiscall hasDMA::hasDMA(class hasDMA const &)" (??0hasDMA##QAE#ABV0##Z)
1>C:\Users\Matt\documents\visual studio 2010\Projects\GSP_125_Lab5\Debug\GSP_125_Lab5.exe : fatal error LNK1120: 1 unresolved externals
The program runs when I delete this block of code:
hasDMA::hasDMA(const hasDMA & hs) : ABC(hs)
{
style = new char[std::strlen(hs.style) + 1];
std::strcpy(style, hs.style);
}
But I don't know what part of that is being referenced elsewhere.
Here is my ABC header and hasDMA header.
class ABC
{
private:
enum {MAX = 35};
char label[MAX];
int rating;
protected:
const char * Label() const {return label;}
int Rating() const {return rating;}
public:
ABC(const char * l = "null", int r = 0);
ABC(const ABC & rs);
virtual ~ABC() {};
virtual ABC & operator*() { return *this; }
ABC & operator=(const ABC & rs);
virtual void View() const = 0;
friend std::ostream & operator<<(std::ostream & os, const ABC & rs);
};
class hasDMA :public ABC
{
private:
char * style;
public:
hasDMA(const char * s = "none", const char * l = "null",
int r = 0);
hasDMA(const char * s, const ABC & rs);
hasDMA(const hasDMA & hs);
~hasDMA(){};
hasDMA & operator=(const hasDMA & rs);
virtual void View() const;
};
These are the only two ABC methods I have:
ABC::ABC(const char *l, int r)
{
std::strcpy(label, l);
label[MAX - 1] = '\0';
rating = r;
}
ABC & ABC::operator=(const ABC & rs)
{
if (this == &rs)
return *this;
strcpy(label, rs.label);
return *this;
}
If it helps these are the rest of my hasDMA methods:
hasDMA::hasDMA(const char *s, const char *l, int r) : ABC (l, r)
{
std::strcpy(style, s);
}
hasDMA::hasDMA(const char *s, const ABC & rs)
{
std::strcpy(style, s);
}
void hasDMA::View() const
{
cout << "Record Label: " << Label() << endl;
cout << "Rating: " << Rating() << endl;
cout << "Style: " << style << endl;
}
hasDMA & hasDMA::operator=(const hasDMA & hs)
{
if (this == &hs)
return *this;
ABC::operator=(hs);
style = new char[std::strlen(hs.style) +1];
std::strcpy(style, hs.style);
return *this;
}
You have declared an ABC copy constructor, but you haven't defined it.
ABC(const ABC & rs); // declaration.
You will need to provide a definition, or remove the declaration.
You could greatly simplify the class by using an std::string instead of the char array. You wouldn't need to provide an assignment operator, copy constructor or destructor.
You forgot to define implementation for ABC(const ABC & rs);