0

I looked at Undefined reference to vtable, but even after adding a destructor I am still met with a similar error:

main.cpp:(.text._ZN8isStringC2Ev[_ZN8isStringC5Ev]+0xf): undefined reference to `vtable for isString'
/usr/bin/ld: /tmp/ccVCX8sf.o: in function `isString::~isString()':
main.cpp:(.text._ZN8isStringD2Ev[_ZN8isStringD5Ev]+0xf): undefined reference to `vtable for isString'
/usr/bin/ld: /tmp/ccVCX8sf.o:(.data.rel.ro._ZTI8MyString[_ZTI8MyString]+0x10): undefined reference to `typeinfo for isString'
/usr/bin/ld: /tmp/ccVCX8sf.o:(.data.rel.ro._ZTI14CStringAdapter[_ZTI14CStringAdapter]+0x10): undefined reference to `typeinfo for isString'
collect2: error: ld returned 1 exit status

The following code is creating my own String class, but using an adapter for cstrings. They (MyString and CStringAdapter classes) inherit from a pure virtual class isString. I'm just trying to understand how to use adapters; I know creating my own string class is quite pointless. I'm using C++ 17.

#include <iostream>
#include <cstring>

using namespace std;

class isString{
public:
    virtual ~isString()=default;
    virtual const char* getBuffer()const;
    virtual size_t size()const;
};

class CStringAdapter: public isString{
protected:
    string str;
public:
    CStringAdapter(): str{""} {}
    CStringAdapter(const char* newStr): str{newStr} {}
    ~CStringAdapter()=default;
    
    const char* getBuffer() const override { return str.c_str(); }
    size_t size() const override { return str.size(); }
};

class MyString: public isString{
protected:
    string str;
public:
    MyString():str{""} {}
    MyString(const char* newCStr) { *this = newCStr; }
    MyString(const MyString& newStr) { *this = newStr; }
    ~MyString()=default;
    
    MyString& Assign(const isString& myStr, const isString& aStr){
        memcpy(const_cast<char*>(myStr.getBuffer()), aStr.getBuffer(), aStr.size());
        return *this;
    }
    MyString& operator=(const MyString& aString){ return Assign(*this, aString); }
    MyString& operator=(const char* aCString){ return Assign(*this, CStringAdapter(aCString)); }

    const char* getBuffer() const override { return str.c_str(); }
    size_t size() const override { return str.size(); }
};

int main()
{
    MyString str1{"Hello World"};
    return 0;
}

1 Answers1

3

You didn't define the member functions isString::getBuffer and isString::size. You need to define them.

If you don't want the class to have definitions for these functions, you must mark them as pure virtual, making isString an abstract base class which cannot be instantiated directly:

virtual const char* getBuffer() const = 0;
virtual size_t size() const = 0;
user17732522
  • 53,019
  • 2
  • 56
  • 105