C++ Virtual Destructor with Unresolved externals [duplicate] - c++

This question already has answers here:
What is an undefined reference/unresolved external symbol error and how do I fix it?
(39 answers)
Closed 4 years ago.
I have two classes..
template <class T>
class Node
{
protected:
Node() = default;
virtual ~Node() = 0;
Node(const T& data) noexcept;
Node(const Node<T> & copy) noexcept;
Node(Node<T> && copy) noexcept;
Node<T> & operator=(const Node<T> & rhs) noexcept;
Node<T> & operator=(Node<T> && rhs) noexcept;
public:
T & GetData() noexcept;
T GetData() const noexcept;
void SetData(const T & data) noexcept;
private:
T data_;
};
template<class T>
class ListNode : public Node<T>
{
public:
ListNode() = default;
ListNode(const T& data, ListNode<T> * next = nullptr, ListNode<T> * previous = nullptr) noexcept;
ListNode(const ListNode<T> & copy) noexcept;
ListNode(ListNode<T> && copy) noexcept;
~ListNode() override = default;
ListNode<T> & operator=(const ListNode<T> & rhs) noexcept;
ListNode<T> & operator=(ListNode<T> && rhs) noexcept;
ListNode<T> * GetNext() noexcept;
ListNode<T> * GetPrevious() noexcept;
void SetNext(ListNode<T> * const next) noexcept;
void SetPrevious(ListNode<T> * const previous) noexcept;
private:
ListNode<T> * next_;
ListNode<T> * previous_;
};
I get an "1 unresolved externals" error. In my previous experience this would usually mean something is wrong with virtual, override, or something like that. I've messed around with this code but can't make the error go away. Any advice?

Derived destructors always implicitly invoke the base destructor at the end of their execution. You have code that is trying to invoke an abstract function. You need to give ~Node() a definition with an empty function body:
virtual ~Node() {};

Related

Operator overload template

I'm trying to implement an operator overload function based on a header file that was given to me, but I'm not understanding one this. Here's what I've been given:
template<class Type>
myClass<Type>& myClass<Type>::operator =(const myClass<Type> &);
My question is in relation to the parameter passed. (const myClass &) indicate a value passed, but how to I reference that value within the function? Normally if I have (const myClass &myValue), I would reference that with myValue=whatever. But I'm not sure how to handle this one.
This is the header file that i'm trying to implement. I'm not asking for anyone to solve this, but I would like some clarifications:
template<class Type>
struct nodeType{
Type value;
nodeType<Type> *next;
nodeType<Type> *prev;
};
template <class Type>
class sortedListADT {
public:
const sortedListADT<Type>& operator=(const sortedListADT<Type> &);
bool isEmpty() const;
bool search(const Type& searchElem) const;
void removeElement(const Type& remElem);
void insertElement(const Type& newElem);
Type front() const;
Type back() const;
void printInOrder() const;
void printRevOrder() const;
void destroyList();
sortedListADT();
sortedListADT(const sortedListADT<Type>& otherList);
~sortedListADT();
private:
nodeType<Type> *first;
nodeType<Type> *last;
int numElements;
void copyList(const sortedListADT<Type>& otherList);
};
how to I reference that value within the function?
We just can't because the parameter is unnamed and for us to use it inside the function it must have a name(to refer to it by that name).
It seems that you're trying to implement the overloaded operator= which you can do as shown below:
template <class Type>
class sortedListADT {
public:
//this is a declaration
const sortedListADT<Type>& operator=(const sortedListADT<Type> &);
//other code as before
};
template<typename Type>
//-----------------------------------------------------------------------------------vvvvvvvvvvvvv--->added a name for the paramter
const sortedListADT<Type>& sortedListADT<Type>::operator=(const sortedListADT<Type> &namedParameer)
{
//add your code here
//don't forget to have a return statement here
}
Working demo

Trouble with begin() of my Map realization

help me with figuring out please why I have this error:
error:
<function-style-cast>: The compiler cannot cast from "const mtm::Node<mtm::MtmMap<int,int,std::less<KeyType>>::Pair> *" to "mtm::MtmMap<int,int,std::less<KeyType>>::iterator"
Those are different relevant parts of the code:
Node:
template <typename DataType>
class Node {
public:
DataType data;
Node<DataType> *head;
Node<DataType> *next;
public:
Node(const DataType& data) :data(data), head(nullptr) {
next = nullptr;
};
Iterator:
class iterator {
private:
Node<Pair>* _ptr = nullptr;
public:
iterator(Node<Pair>* ptr = nullptr) : _ptr(ptr) { }
iterator(const iterator& itr) = default;
~iterator() = default;
iterator& operator=(const iterator&) = default;
Private of MtmMap:
private:
Node<Pair> _pairs;
iterator _it;
int _size;
The code when the error shows:(in body of MtmMap)
iterator begin() const{
if (this->_size) {
this->_it = iterator(&_pairs);
}
return this->_it;
}
The problem is that you've declared begin as const. Thus this in this line:
this->_it = iterator(&_pairs);
&_pairs has resulting type of const Node<Pair>*. Your iterator class only accepts a non-const pointer to Node<Pair> (implicit conversion from a const-pointer to a non-const-pointer is not allowed).
Either iterator needs to be modified to accept (and store) a const-pointer, or begin needs to drop the const qualifier.

iterator on map of pointers to objects as a key c++

i'm implementing a backtracking algorithm to solve sudokus, but i have some issues using maps.
could any one tell me why i get these two errors when compiling my code? the first error is about the line declaring the iterator on the map. the second one is when doing Adj[&node] = mList;
the errors:
Error C2664 'std::_Tree_const_iterator>>> std::_Tree>::find(Node *const &) const' : can't convert argument 1 from 'const Node *' to 'Node *const &'
Error C2679 '[' binary : no operator found accepting a right operand of type 'const Node *' (ou there's no acceptable conversion)
(my Visual studio is in french, so i translated the error messages. hope it's fine like this)
my code where i got the error:
template<class T>
void AdjList<T>::addElement(const Node<T>& node, const vector<Node<T>>& vecOfNeighbours) {
typename map< Node<T>*, LinkedList<T>>::iterator mit = Adj.find(&node);
if (mit!=Adj.end()) {
LinkedList<T> mList;
for (typename vector<Node<T>>::const_iterator it = vecOfNeighbours.begin(); it != vecOfNeighbours.end(); it++) {
mList.Add((*it).getValue()[0]);
}
Adj[&node] = mList;
}
}
my classes définitions :
template<class T>
class AdjList
{
private:
map<Node<T>*, LinkedList<T>> Adj;
public:
AdjList();
AdjList(const AdjList<T>& adjlist);
AdjList(const Node<T>& node, const vector<Node<T>>& vecOfNeighbours);
void addElement(const Node<T>& node, const vector<Node<T>>& vecOfNeighbours);
void Print() const;
};
template<class T>
class LinkedList
{
Node<T>* head;
int getEndList();
Node<T>* returnFrontEnd(void) const;
public:
LinkedList();
LinkedList(T data);
LinkedList(const LinkedList<T>& list);
LinkedList<T>& operator=(const LinkedList<T>& list);
void Add(T data);
void AddAt(int index, T data);
void Print();
~LinkedList();
};
template<class T>
class Node
{
protected:
vector<T> _value;
Node<T>* child;
public:
Node(T value);
void addValue(T value);
Node<T>* clone() const;
Node(const Node<T>& node);
vector<T> getValue() const;
Node<T>* returnChild() const;
void AddChild(const Node<T>& node);
Node& operator=(const Node<T>& node);
~Node();
};
You need to cast away const. Why? Take a look:
void AdjList<T>::addElement(const Node<T>& node, const vector<Node<T>>&)
Okay, so node is a const reference,
typename map< Node<T>*, LinkedList<T>>::iterator mit = Adj.find(&node);
But this iterator will have a non-const pointer. So if this were allowed, you'd be able to get a non-const pointer from a const reference. That clearly requires casting away const (which you don't do).

linked list operator overloading issue

i tried to build up my own linked list class and got a problem with the = operator overloading. as far as i know, we should use const parameter when overloading the assignment operator, say using linked_list<T>& operator=( const linked_list<T>& a). however, the complier gave me errors unless i put linked_list<T>& a instead. the complier would stop at
if(this->head==a.front()), giving me Error
11 error C2662: 'linked_list<T>::front' : cannot convert 'this' pointer from 'const linked_list<T>' to 'linked_list<T> &'
below are the details.
#ifndef _LINKED_LIST_H_
#define _LINKED_LIST_H_
template <class T>
struct node
{
T data;
node<T>* next;
};
template <class T>
class linked_list
{
private:
node<T>* head;
public:
linked_list<T>();
linked_list<T>(const linked_list<T>& a);
~linked_list<T>();
linked_list<T>& operator=(const linked_list<T>& a);
bool isEmpty();
int size() const;
void insert_front(T a);
void insert_end(T a);
void erase_end();
void erase_front();
void print() const;
void erase(node<T>* a);
node<T>*& front()
{
node<T>* ptr = new node<T>;
ptr = head;
return ptr;
}
void setFront(node<T>* a);
};
#endif
template <class T>
linked_list<T>& linked_list<T>::operator=(const linked_list<T>& a)
{
if (this->head == a.front()) // the error mentioned happened here. however,
// if no const in the parameter, it would be
// no error
{
return *this;
}
while (head != nullptr) erase_front();
node<T>* copy;
copy = a.front();
while (copy->next != nullptr)
{
insert_end(copy->data);
copy = copy->next;
}
return *this;
}
anybody can help? thanks.
When an accessor returns a reference to an owned structure, it's usually a good idea to implement two versions: One which is non-const and returns a non-const reference, and one which is const and returns a const reference. That way it can be used in both mutating and non-mutating contexts. front() would be a good candidate for this.
Though a side note -- you probably don't want to expose your nodes in the public linked_list interface, particularly non-const references to them. That's the sort of thing to encapsulate entirely in the class.
The problem is that front() is not a const member function, and you're trying to call it on a const instance.

C++ Template Limiting Member Constructor

This is my first foray into C++ templates, and I'm trying to construct a BinaryTree template to help me with a Project Euler problem; however, I seem to be getting an error where BinaryTree class doesn't recognize all the constructors of the BinaryTreeNode! Here's a snippet of the code.
template <class T>
class BinaryTreeNode
{
private:
BinaryTreeNode<T>* _left;
BinaryTreeNode<T>* _right;
T* _value;
public:
BinaryTreeNode();
explicit BinaryTreeNode(const T& value) : _value(&(T(value))) {}
BinaryTreeNode(BinaryTreeNode<T>& left, BinaryTreeNode<T>& right, const T& value) :
_left(&left), _right(&right), _value(&(T(value))){}
};
The BinaryTree class
#include "BinaryTreeNode.h"
template <class T>
class BinaryTree
{
private:
BinaryTreeNode<T>* _root;
BinaryTreeNode<T>* _current;
unsigned int size;
public:
BinaryTree() : size(0), _root(0), _current(0) { }
explicit BinaryTree(BinaryTree<T>& leftTree, BinaryTree<T>& rightTree, const T& value) :
size(leftTree.Size() + rightTree.Size() + 1), _root(leftTree.Root(), rightTree.Root(), value), _current(_root) {}
explicit BinaryTree(const T& value) : size(1), _root(value) {}
const BinaryTreeNode<T>& Root() const { return *_root;}
};
I'm getting these errors.
error C2359: 'BinaryTree<T>::_root' : member of non-class type requires single initializer expression
error C2440: 'initializing' : cannot convert from 'const int' to 'BinaryTreeNode<T> *'
error C2439: 'BinaryTree<T>::_root' : member could not be initialized
The BinaryTreeNode constructor of (BinaryTreeNode<T>&, BinaryTreeNode<T>&, const T& value) works when I include it in my main code, but it doesn't seem to work under my BinaryTree template. Anyone know why?
In your initialization expression _root(leftTree.Root(), rightTree.Root(), value), _root is a pointer. You can only initialize it to another pointer. Perhaps you mean to initialize it to a pointer to a new node constructed on those arguments?
This could be done like this: (updated after your edit)
_root(new BinaryTreeNode<T>(leftTree.Root(), rightTree.Root(), value))
However, this is very dangerous (think about an exception in the allocation), and you should probably avoid using raw pointers in your class design and instead use smart managing pointers.
Similarly, the initializer _root(value) does the wrong thing, you might want:
_root(new BinaryTreeNode<T>(value))
(Also note that you should initialize members in their order of declaration.)
Update: I changed the first constructor call following your edit, but as #Luc says, your constructors take non-const arguments but Root() only provides a const reference, so you still need to fix that.
You have missed ; after both class declarations!
template <class T>
class BinaryTreeNode
{
private:
BinaryTreeNode<T>* _left;
BinaryTreeNode<T>* _right;
T* _value;
public:
BinaryTreeNode();
explicit BinaryTreeNode(const T& value) : _value(&(T(value))) {}
BinaryTreeNode(BinaryTreeNode<T>& left, BinaryTreeNode<T>& right, const T& value) :
_left(&left), _right(&right), _value(&(T(value))){}
};
template <class T>
class BinaryTree
{
private:
BinaryTreeNode<T>* _root;
BinaryTreeNode<T>* _current;
unsigned int size;
public:
BinaryTree() : size(0), _root(0), _current(0) { }
explicit BinaryTree(BinaryTree<T>& leftTree, BinaryTree<T>& rightTree, const T& value) :
size(leftTree.Size() + rightTree.Size() + 1), _root(leftTree.Root(), rightTree.Root(), value), _current(_root) {}
explicit BinaryTree(const T& value) : size(1), _root(value) {}
};
I believe that you need a constructor in the form BinaryTree<T>();