1

I'm creating a cpp program using functions that are applied to C++11. Even though the code seems correct and has no syntax errors i'm getting this message when i compile:

/tmp/cce9dpew.o: In function `Object::Object()':
classes.cpp:(.text+0xd): undefined reference to `vtable for Object'
/tmp/cce9dpew.o: In function `Object::~Object()':
classes.cpp:(.text+0x45): undefined reference to `vtable for Object'
/tmp/cce9dpew.o:(.rodata._ZTI6String[_ZTI6String]+0x10): undefined reference to `typeinfo for Object'
collect2: error: ld returned 1 exit status

I have to add here that if i put all those .cpp and .h files in one it runs Aok printing constructor and destructor cout's just fine. Can someone help?The code is below. compile recipe i used to run them all together: g++ -std=c++0x classes.h classes.cpp mainiz.cpp

classes.h:

#ifndef CLASSES_H
#define CLASSES_H

#include <iostream>
#include <cstring>
using namespace std;

class Object
{
    private:
        int id;
    public:
        Object();
        ~Object();
        void set_id(int ids);
        int get_id();
        void Equal(Object* bj) const;
        void Identical(Object* bj) const;
        virtual Object* clone();
        virtual void toString();        
};


class String:public Object
{
        string characters;
    public:
        String();
        ~String();
        void set_char(string a);
        string get_char();
        String* clone();
        void toString();    
        int Length();
        void Clear(string a);
        string& Concat(string &a);
        char At(char b);
        string& UpdateAt(string a,string charact);
        void Print(const string a) const;   
};

#endif //CLASSES_H

classes.cpp:

#include <iostream>
#include <cstring>

#include "classes.h"

using namespace std;

//FOR OBJECT CLASS
Object::Object(){ cout << "An object just got created." << endl;}

Object::~Object(){ cout << "An object just got destroyed." << endl; }

void Object::set_id(int ids) { this->id = ids; }
int Object::get_id() { return this->id;}

void Object::Equal(Object* bj) const
{
    if((this->id == bj->id))
    {
        cout << "The objects are equal." << endl;
    }
    else
    {
        cout << "The objects are not equal." <<endl;
    }
}

void Object::Identical(Object* bj) const
{
    if(this==bj)
    {
        cout << "The objects are identical." <<endl;
    }
    else
    {
        cout << "The objects are not identical." <<endl;
    }
}

//FOR STRING CLASS
String::String(){ cout << "String just created" << endl;}

String::~String(){ cout << "String to be destroyed" << endl;}

void String::set_char(string a) { this->characters = a;}
string String::get_char() { return this->characters;}

String* String::clone() { return this;}
void String::toString() {cout << "characters" << endl;}

int String::Length()
{ 
    string a = this->characters;
    return a.length();  
}

void String::Clear(string a)
{
    this->characters.clear();
}

string& String::Concat(string &a){  return (this->characters.append(a));}

char String::At(char b) { return (this->characters.find(b)); }

string& String::UpdateAt(string a,string charact)
{
    int position=this->characters.find(charact);
    return this->characters.replace(position,1,a);  
}

void String::Print(const string a) const { cout << "print of string:" << a << endl; }

mainiz.cpp:

#include <iostream>
#include <cstring>

#include "classes.h"

using namespace std;

int main()
{
    Object k;
    Object *st = new String;
    String d;
}
Ken Y-N
  • 14,644
  • 21
  • 71
  • 114
  • Does this answer your question? [What is an undefined reference/unresolved external symbol error and how do I fix it?](https://stackoverflow.com/questions/12573816/what-is-an-undefined-reference-unresolved-external-symbol-error-and-how-do-i-fix) – Thomas Sablik Jan 17 '20 at 00:04
  • On a side note or two, [don't do `using namespace std;`](https://stackoverflow.com/q/1452721/1270789), and `Print()` shouldn't take an `std::string` parameter. – Ken Y-N Jan 17 '20 at 00:35
  • @ThomasSablik thank you for sharing this link! well i read it and from what i understood i have to change something with my virtuals or make my constructors virtual ? – ScatterBrainer Jan 17 '20 at 12:42
  • @KenY-N why shouldn't i use it though?I would have to write std:: in front of everything in my functions..Why wouldn't you suggest it? – ScatterBrainer Jan 17 '20 at 12:43
  • @ScatterBrainer Igor Tandetnik provided the solution to your problem. – Thomas Sablik Jan 17 '20 at 13:15

3 Answers3

2

Making the destructor for Object class "virtual" you would get another error for undefined reference to Object::clone and Object::toString.

You can try what @Igor suggested, but your current mainiz.cpp code won't work because C++ doesn't allow an instance of a class with pure virtual methods.

You can try the following code:

class Object {
  virtual ~Object();

  virtual Object* clone();
  virtual void toString();
};

Object* Object::clone() {
  // Make your implementation here
  return nullptr;
}

void Object::toString() {
  // Make your implementation here
}
segoqu
  • 19
  • 3
  • Thanks for the answer! "because C++ doesn't allow an instance of a class with pure virtual methods." ....I'm having trouble understanding this...Can you please explain it a little bit? – ScatterBrainer Jan 17 '20 at 12:46
  • Sure, a virtual table store virtual methods to use later for every instance. A virtual table allows C++ classes inheritance, as you might know already, a child is only allowed to override the virtual methods of the parent, I understand it as replace the parent's method with the child's method in the vtable. A pure virtual method is declared as: "virtual void MyMethod() = 0;", this means that MyMethod doesn't have a body, and the field in the vtable is empty, so when the linker search for the definition of that method it gets a trouble because it doesn't know which definition to use. – segoqu Jan 18 '20 at 00:51
  • And the instance is incomplete because it has declared methods without actual code. Hope I solved your doubts. [Here a reference](https://www.learncpp.com/cpp-tutorial/125-the-virtual-table/) – segoqu Jan 18 '20 at 00:58
1

Object::clone and Object::toString are declared but never implemented.

If you want to leave them unimplemented, make them pure virtual, as in

class Object {
  virtual Object* clone() = 0;
};
Igor Tandetnik
  • 50,461
  • 4
  • 56
  • 85
  • The problem is that i don't want users to be allowed to clone Object or to use toString for Object...Must it be implemented? – ScatterBrainer Jan 17 '20 at 12:48
  • @ScatterBrainer `clone` is not implemented. Do you see `= 0;` at the end? But you can't create an instance of `Object` if it's an abstract class. – Thomas Sablik Jan 17 '20 at 13:17
  • @ThomasSablik yes i don't want to implement it! Is Object abstract? – ScatterBrainer Jan 17 '20 at 14:12
  • @ScatterBrainer A class that contains pure virtual methods is an abstract class so yes, `Object` is abstract – Thomas Sablik Jan 17 '20 at 14:22
  • @ThomasSablik the code that i gave does not include any pure virtual functions so the way i did it is object abstract? – ScatterBrainer Jan 18 '20 at 13:47
  • @ScatterBrainer the way you did it is simply wrong. You declared methods but you didn't define them. To fix this you have to either define the methods or declare them as pure virtual. – Thomas Sablik Jan 18 '20 at 13:56
0

None of the solutions given above were correct.The problem was within my compilation recipe.These functions started existing after C++11 so if you're using something like that your compilation recipe should be:

g++ -g -std=c++11 -o executable file.cpp main.cpp