проблемы с dynamic_cast в C ++ - PullRequest
       88

проблемы с dynamic_cast в C ++

0 голосов
/ 25 февраля 2020

Я реализую неоднородный связанный список (файлы. cpp и .h ниже) в C ++.

Компиляция в Linux с использованием компилятора Intel с: icpc test.cpp List.cpp -o test дает много ошибок (см. Ниже). Кажется, что проблема возникает из строк, содержащих dynamic_cast в List.cpp. Синтаксис мне кажется правильным. Может ли кто-нибудь помочь мне определить проблему?

/tmp/icpcIuHg7X.o: In function `InhomList::getPrev(std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> > const&)':
List.cpp:(.text+0x25): undefined reference to `typeinfo for BaseEl'
/tmp/icpcIuHg7X.o: In function `InhomList::getPos(std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> > const&)':
List.cpp:(.text+0x134): undefined reference to `typeinfo for BaseEl'
/tmp/icpcIuHg7X.o: In function `InhomList::insertAfter(std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> > const&, Cell*)':
List.cpp:(.text+0x267): undefined reference to `vtable for BaseEl'
List.cpp:(.text+0x346): undefined reference to `vtable for BaseEl'
/tmp/icpcIuHg7X.o: In function `InhomList::insertAfter(std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> > const&, std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> > const&, Cell*)':
List.cpp:(.text+0x43b): undefined reference to `vtable for BaseEl'
List.cpp:(.text+0x4c8): undefined reference to `vtable for DerivedEl'
List.cpp:(.text+0x59c): undefined reference to `BaseEl::~BaseEl()'
List.cpp:(.text+0x5c9): undefined reference to `vtable for BaseEl'
List.cpp:(.text+0x659): undefined reference to `vtable for DerivedEl'
List.cpp:(.text+0x71c): undefined reference to `BaseEl::~BaseEl()'
/tmp/icpcIuHg7X.o: In function `InhomList::erasePos(Cell*)':
List.cpp:(.text+0x756): undefined reference to `typeinfo for BaseEl'
/tmp/icpcIuHg7X.o: In function `InhomList::InhomList(InhomList const&)':
List.cpp:(.text+0x8c3): undefined reference to `typeinfo for DerivedEl'
List.cpp:(.text+0x8d5): undefined reference to `typeinfo for DerivedEl'
List.cpp:(.text+0x915): undefined reference to `typeinfo for DerivedEl'
List.cpp:(.text+0x97c): undefined reference to `typeinfo for BaseEl'
List.cpp:(.text+0xa61): undefined reference to `vtable for BaseEl'
List.cpp:(.text+0xaf4): undefined reference to `vtable for DerivedEl'
List.cpp:(.text+0xb7c): undefined reference to `typeinfo for BaseEl'
List.cpp:(.text+0xc97): undefined reference to `vtable for BaseEl'
List.cpp:(.text+0xd4d): undefined reference to `BaseEl::~BaseEl()'
List.cpp:(.text+0xdad): undefined reference to `vtable for BaseEl'
List.cpp:(.text+0xe4a): undefined reference to `vtable for DerivedEl'
List.cpp:(.text+0xf1c): undefined reference to `BaseEl::~BaseEl()'
List.cpp:(.text+0xf7b): undefined reference to `vtable for BaseEl'
/tmp/icpcIuHg7X.o: In function `InhomList::InhomList(InhomList const&)':
List.cpp:(.text+0x1063): undefined reference to `typeinfo for DerivedEl'
List.cpp:(.text+0x1075): undefined reference to `typeinfo for DerivedEl'
List.cpp:(.text+0x10b5): undefined reference to `typeinfo for DerivedEl'
List.cpp:(.text+0x111c): undefined reference to `typeinfo for BaseEl'
List.cpp:(.text+0x1201): undefined reference to `vtable for BaseEl'
List.cpp:(.text+0x1294): undefined reference to `vtable for DerivedEl'
List.cpp:(.text+0x131c): undefined reference to `typeinfo for BaseEl'
List.cpp:(.text+0x1437): undefined reference to `vtable for BaseEl'
List.cpp:(.text+0x14ed): undefined reference to `BaseEl::~BaseEl()'
List.cpp:(.text+0x154d): undefined reference to `vtable for BaseEl'
List.cpp:(.text+0x15ea): undefined reference to `vtable for DerivedEl'
List.cpp:(.text+0x16bc): undefined reference to `BaseEl::~BaseEl()'
List.cpp:(.text+0x171b): undefined reference to `vtable for BaseEl'
/tmp/icpcIuHg7X.o: In function `InhomList::operator=(InhomList const&)':
List.cpp:(.text+0x18eb): undefined reference to `typeinfo for DerivedEl'
List.cpp:(.text+0x18fd): undefined reference to `typeinfo for DerivedEl'
List.cpp:(.text+0x193d): undefined reference to `typeinfo for DerivedEl'
List.cpp:(.text+0x19a4): undefined reference to `typeinfo for BaseEl'
List.cpp:(.text+0x1a89): undefined reference to `vtable for BaseEl'
List.cpp:(.text+0x1b1c): undefined reference to `vtable for DerivedEl'
List.cpp:(.text+0x1ba4): undefined reference to `typeinfo for BaseEl'
List.cpp:(.text+0x1cbf): undefined reference to `vtable for BaseEl'
List.cpp:(.text+0x1d79): undefined reference to `BaseEl::~BaseEl()'
List.cpp:(.text+0x1dd9): undefined reference to `vtable for BaseEl'
List.cpp:(.text+0x1e76): undefined reference to `vtable for DerivedEl'
List.cpp:(.text+0x1f48): undefined reference to `BaseEl::~BaseEl()'
List.cpp:(.text+0x1fa7): undefined reference to `vtable for BaseEl'
/tmp/icpcIuHg7X.o: In function `InhomList::insert(std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> > const&)':
List.cpp:(.text+0x2086): undefined reference to `typeinfo for BaseEl'
List.cpp:(.text+0x2160): undefined reference to `vtable for BaseEl'
List.cpp:(.text+0x223f): undefined reference to `vtable for BaseEl'
/tmp/icpcIuHg7X.o: In function `InhomList::insert(std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> > const&, std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> > const&)':
List.cpp:(.text+0x231b): undefined reference to `typeinfo for BaseEl'
List.cpp:(.text+0x23f7): undefined reference to `vtable for BaseEl'
List.cpp:(.text+0x2488): undefined reference to `vtable for DerivedEl'
List.cpp:(.text+0x2560): undefined reference to `BaseEl::~BaseEl()'
List.cpp:(.text+0x258e): undefined reference to `vtable for BaseEl'
List.cpp:(.text+0x261f): undefined reference to `vtable for DerivedEl'
List.cpp:(.text+0x26e6): undefined reference to `BaseEl::~BaseEl()'
/tmp/icpcIuHg7X.o: In function `InhomList::erase(std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> > const&)':
List.cpp:(.text+0x2716): undefined reference to `typeinfo for BaseEl'
List.cpp:(.text+0x2789): undefined reference to `typeinfo for BaseEl'
List.cpp:(.text+0x279f): undefined reference to `typeinfo for BaseEl'
List.cpp:(.text+0x27e6): undefined reference to `typeinfo for BaseEl'
List.cpp:(.text+0x27f8): undefined reference to `typeinfo for BaseEl'
/tmp/icpcIuHg7X.o:List.cpp:(.text+0x281c): more undefined references to `typeinfo for BaseEl' follow

test. cpp: program

#include "List.h"
#include <typeinfo>

int main() {


    return 0;
}

cell.h: Определение классов Cell, BaseEl и DerivedEl

    // --------------------------------------------------------
    #ifndef _CELL_
    #define _CELL_
    #include <string>
    #include <iostream>
    using namespace std;

    // Abstract class
    class Cell {
    private:
        Cell *next;
    protected:
        Cell(Cell *suc = NULL) :
                next(suc) {
            ;
        }
    public:
        virtual ~Cell() {
        }

        // Access methods:
        Cell* getNext(void) const {
            return next;
        }
        void setNext(Cell *suc) {
            next = suc;
        }

        virtual void display() const = 0;
    };

    class BaseEl: public Cell {
    private:
        string name;
    public:
        BaseEl(Cell *suc = NULL, const string &s = "") :
                Cell(suc), name(s) {
            ;
        }
        ~BaseEl();

        // Access methods:
        const string& getName(void) const {
            return name;
        }
        void setName(const string &s) {
            name = s;
        }

        void display() const {
            cout << endl << "------------------------------" << endl << "Name: "
                    << name << endl;
        }
    };

    class DerivedEl: public BaseEl {
    private:
        string rem;
    public:
        DerivedEl(Cell *suc = NULL, const string &s = "", const string &b = "") :
                BaseEl(suc, s), rem(b) {
            ;
        }
        ~DerivedEl();

        // Access methods:
        const string& getRem(void) {
            return rem;
        }
        void setRem(const string &s) {
            rem = s;
        }

        void display() const {
            BaseEl::display();
            cout << "Remark: " << rem << endl;
        }
    };

    #endif

List.h: определение класса InhomList.h

// --------------------------------------------------------
#ifndef _LIST_
#define _LIST_
#include "cell.h"
using namespace std;

class InhomList {
private:
    Cell *first;
protected:
    Cell* getPrev(const string &s);
    Cell* getPos(const string &s);
    void insertAfter(const string &s, Cell *prev);
    void insertAfter(const string &s, const string &b, Cell *prev);
    void erasePos(Cell *pos);
public:
    InhomList() {
        first = NULL;
    }
    InhomList(const InhomList &src);
    ~InhomList();
    InhomList& operator=(const InhomList &src);
    void insert(const string &n);
    void insert(const string &n, const string &b);
    void erase(const string &n);
    void displayAll() const;
};

#endif

List. cpp: методы List.h

#include "List.h"
#include <typeinfo>

// Copy constructor:
InhomList::InhomList(const InhomList &src) {
    // Append the elements from src to the empty list.
    first = NULL;
    Cell *pEl = src.first;
    for (; pEl != NULL; pEl = pEl->getNext()) {

        if (typeid(*pEl) == typeid(DerivedEl)) {
            insert(dynamic_cast<DerivedEl*>(pEl)->getName(),
                    dynamic_cast<DerivedEl*>(pEl)->getRem());
        } else
            insert(dynamic_cast<BaseEl*>(pEl)->getName());

    }
}

// Destructor:
InhomList::~InhomList() {
    Cell *pEl = first, *next = NULL;
    while (pEl != NULL) {
        next = pEl->getNext();
        delete pEl;
        pEl = next;
    }
}

// Assignment:
InhomList& InhomList::operator=(const InhomList &src) {
    // To free storage for all elements:
    Cell *pEl = first, *next = NULL;
    while (pEl != NULL) {
        next = pEl->getNext();
        delete pEl;
        pEl = next;
    }
    first = NULL; // Empty list
    pEl = src.first; // Copy the elements from src to the empty list
    for (; pEl != NULL; pEl = pEl->getNext())
        if (typeid(*pEl) == typeid(DerivedEl))
            insert(dynamic_cast<DerivedEl*>(pEl)->getName(),
                    dynamic_cast<DerivedEl*>(pEl)->getRem());
        else
            insert(dynamic_cast<BaseEl*>(pEl)->getName());
    return *this;
}

void InhomList::insert(const string &n) {
    Cell *pEl = getPrev(n);
    insertAfter(n, pEl);
}

void InhomList::insert(const string &n, const string &b) {
    Cell *pEl = getPrev(n);
    insertAfter(n, b, pEl);
}

void InhomList::erase(const string &n) {
    erasePos(getPos(n));
}

void InhomList::displayAll() const {
    Cell *pEl = first;
    while (pEl != NULL) {
        pEl->display();
        pEl = pEl->getNext();
    }
}

Cell* InhomList::getPrev(const string &n) {
    Cell *pEl = first, *prev = NULL;
    while (pEl != NULL) {
        if (n > dynamic_cast<BaseEl*>(pEl)->getName()) {
            prev = pEl;
            pEl = pEl->getNext();
        } else
            return prev;
    }
    return prev;
}

Cell* InhomList::getPos(const string &n) {
    Cell *pEl = first;
    while (pEl != NULL && (n != dynamic_cast<BaseEl*>(pEl)->getName()))
        pEl = pEl->getNext();
    if (pEl != NULL && n == dynamic_cast<BaseEl*>(pEl)->getName())
        return pEl;
    else
        return NULL;
}

void InhomList::insertAfter(const string &s, Cell *prev) {
    if (prev == NULL) // Insert at the beginning:
        first = new BaseEl(first, s);
    else // In the middle or at the end:
    {
        Cell *p = new BaseEl(prev->getNext(), s);
        prev->setNext(p);
    }
}

void InhomList::insertAfter(const string &s, const string &b, Cell *prev) {
    if (prev == NULL) // Insert at the beginning:
        first = new DerivedEl(first, s, b);
    else // In the middle or at the end:
    {
        Cell *p = new DerivedEl(prev->getNext(), s, b);
        prev->setNext(p);
    }
}

void InhomList::erasePos(Cell *pos) {
    Cell *temp;
    if (pos != NULL)
        if (pos == first) // Delete the first element
                {
            temp = first;
            first = first->getNext();
            delete temp;
        } else // Delete from the middle or at the end
        { // Get the predecessor
            temp = getPrev(dynamic_cast<BaseEl*>(pos)->getName());
            if (temp != NULL) // and bend pointer.
                temp->setNext(pos->getNext());
            delete pos;
        }
}

1 Ответ

2 голосов
/ 25 февраля 2020

Можно начать с исправления этой ошибки:

undefined reference to `BaseEl::~BaseEl()'

Эта ошибка произошла из-за того, что вы объявили BaseEl::~BaseEl():

~BaseEl();

, но не указали определение. Вы можете предоставить определение как ~BaseEl() override {}, или ~BaseEl() override = default;, или определить его вне строки в cell.cpp или аналогичном файле.

Аналогично, вам нужно убедиться, что DerivedEl::~DerivedEl() дано определение.

Если я не ошибаюсь, предоставление этих определений избавит от ошибок «неопределенная ссылка на vtable» и «неопределенная ссылка на typeinfo». См. здесь для возможного объяснения.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...