Well, I have three classes:
template<typename E>
class Iterator {
public:
virtual ~Iterator() {
}
virtual bool hasNext() const = 0;
virtual const E& next() = 0;
};
template<typename E>
class IteratorPtr {
private:
Iterator<E>* iterator;
IteratorPtr(const IteratorPtr<E>&);
IteratorPtr<E>& operator=(const Iterator<E>&);
public:
IteratorPtr(Iterator<E>* it)
: iterator(it) {
}
~IteratorPtr() {
delete iterator;
}
Iterator<E>* operator->() const {
return iterator;
}
};
template<typename E>
class Collection
{
public:
virtual void add(const E & value) = 0;
virtual void add(const Collection<E>& collection);
virtual bool remove(const E& value) = 0;
virtual void clear() = 0;
virtual ~Collection()
{
}
virtual bool isEmpty() const = 0;
virtual int size() const = 0;
virtual bool contains(const E& value) const = 0;
virtual Iterator<E>* iterator() const = 0;
};
void Collection<E>::add(const Collection<E>& collection)
{
for (IteratorPtr<E> i(collection.iterator()); i->hasNext();) {
this->add(i->next());
}
}
Obs: all Set's methods are implemented.
template<typename E>
class Set;
template<typename E>
class SortedSet;
template<typename E>
class SetIterator;
template<typename E>
class SetNode {
private:
friend class Set<E> ;
friend class SortedSet<E> ;
friend class SetIterator<E> ;
SetNode()
: next(NULL) {
}
SetNode(E value)
: value(value), next(NULL) {
}
SetNode(E value, SetNode * next)
: value(value), next(next) {
}
~SetNode() {
}
private:
E value;
SetNode * next;
};
template<typename E>
class SetIterator: public Iterator<E> {
private:
friend class Set<E> ;
SetIterator(SetNode<E> * head)
: node(head) {
}
~SetIterator() {
}
bool hasNext() const {
return node != NULL;
}
const E & next() {
E& value = node->value;
node = node->next;
return value;
}
private:
SetNode<E> * node;
};
template<typename E>
class Set: public Collection<E> {
public:
Set(): numNodes(0), head(NULL) {
}
virtual ~Set() {
clear();
}
virtual void add(const E & value);
virtual bool remove(const E& value);
virtual void clear();
virtual bool isEmpty() const;
virtual int size() const;
virtual bool contains(const E& value) const;
virtual Iterator<E>* iterator() const;
private:
Set(const Set & obj): numNodes(0), head(NULL) {
}
virtual bool contains(const E & value, SetNode<E> * & previ) const;
protected:
int numNodes;
SetNode<E> * head;
};
template<typename E>
class SortedSet: public Set<E> {
private:
virtual bool contains(const E& value, SetNode<E> *& prev) const;
public:
SortedSet(): Set<E>() {
}
virtual void add(const E & value);
virtual ~SortedSet() {
this->clear();
}
};
Set and SortedSet don't implement add methods, cause they should do exactly what Collection::add(const Collection& c) does.
int main() {
Set<int> *s = new Set<int>();
s->add(10);
s->add(30);
s->add(12);
s->remove(10);
if (s->contains(30))
puts("Tem");
SortedSet<int> *ss = new SortedSet<int>();
ss->add(*s);
return 0;
}
but this code get a error in the line "ss->add(*s);", saying: no matching to ‘SortedSet::add(Set&)’
Why is this happening?
Now you've posted all the relevant code, the problem is that you've declared another function with the same name in Set:
virtual void add(const E & value);
This hides anything with the same name in the base class; so Collection::add is not accessible via a reference to Set or any of its subclasses.
To fix it, add a using-declaration to Set, to bring Collection::add into the scope of Set:
public:
using Collection::add;
Related
i have a class:
template <typename T>
class List {
private:
struct pointNode {
T data;
pointNode* next;
pointNode* prev;
pointNode() :data(0), next(nullptr), prev(nullptr) {}
pointNode(T n_data) : data(n_data), next(nullptr), prev(nullptr) {}
const T& getValue() {
return this->data;
}
};
pointNode* head;
pointNode* tail;
public:
class Iterator {
//friend class List;
using Iterator_type = List<T>::pointNode;
public:
Iterator(Iterator_type* rNode) {
current_node = rNode;
}
bool operator !=(const Iterator& pNode) {
return this->current_node != pNode.current_node;
}
T const get_value() {
return this->current_node->data;
}
private:
Iterator_type* current_node;
};
List() : head(nullptr), tail(nullptr) {}
inline void InsertFront(T&& val);
inline void InsertBack(T&& val);
inline bool is_empty();
inline void Insert_after_v(T&&searchVal,T&&val);
inline void Insert_after_p(int pos, T&& val);
};
I'm trying to write a function that inserts an element after a given:
template<typename T>
inline void List<T>::Insert_after(Iterator pos, T&& val)
{
pointNode* new_node = new pointNode(std::move(val), ... );
}
as the 2 parameters of the constructor pointNode,i need to get the value of the iterator
private:
Iterator_type* current_node;
And I think it's the right thing to do ?make a friend:
struct pointNode {
friend class Iterator
But I often see that friend is not a particularly good style.
class Iterator
{
public:
Iterator_type* get_current_node() const {
return current_node;
}
or write something like this :
class Iterator
{
public:
Iterator_type* get_node() const {
return current_node;
}
But it seems to me that it is not very good to let the user get private data.So maybe who knows how to do the right thing in such situations?I would be grateful for your advice
I created a List with a template Node class to hold different data types such as Node<int> but also more complex types such as Node<BaseEvent*>.
I also have an event container class to hold different event objects so it has a member argument
List<BaseEvent*> events;
where BaseEvent is an abstract class with derived classes that are not abstract.
In the event container I have a method called "add" (see below) that adds a new event to that events.
BaseEvent* eventClone = event.clone();
The clone returns a pointer to a new derived object such as:
new OpenEvent(*this);
Once it calls the list's insert method, it instantiates a new Node (see below), and in the Node constructor it assigns the value like so:
value(new T(new_value))
So basically it allocates a pointer memory (T=BaseEvent*).
I think I might be losing the eventClone pointer and have a memory leak.
The problem is that when I debugged it I saw that both: T* value; (aka BaseEvent** value) and BaseEvent* eventClone have the same address in memory.
I'm not sure if when I do delete value in the destructor of Node it will just free the pointer allocation to BaseEvent* or also the data that it holds.
Any insights are welcome!
Relevant code snippets
Node<T>
template <class T>
class Node
{
public:
Node(const T& new_value, Node* new_next = NULL, Node* new_prev = NULL);
~Node();
const T& getValue() const;
Node<T>* getNext() const;
Node<T>* getPrev() const;
void setNext(Node* node);
void setPrev(Node* node);
private:
T* value;
Node* next;
Node* prev;
};
template <class T>
Node<T>::Node(const T& new_value, Node* new_next, Node* new_prev) :
value(new T(new_value))
{
next = new_next;
prev = new_prev;
}
template <class T>
Node<T>::~Node()
{
delete value;
}
...
Linked list that uses Node<T>
template <class T>
class List
{
public:
List();
~List();
int getSize() const;
Node<T>* getFirst() const;
Node<T>* getNext(Node<T>& node) const;
Node<T>* getPrev(Node<T>& node) const;
void insertStart(const T& data);
void insertLast(const T& data);
void insertAfter(Node<T>& target, const T& data);
void insertBefore(Node<T>& target, const T& data);
void removeNode(Node<T>& node);
bool contains(const T data);
private:
Node<T>* head;
int size;
};
template <class T>
List<T>::List() : head(NULL), size(0)
{
}
template <class T>
List<T>::~List()
{
Node<T>* temp;
while (head)
{
temp = head;
head = head->getNext();
delete temp;
size--;
}
}
...
template <class T>
void List<T>::insertStart(const T& data) {
if (size == 0)
{
head = new Node<T>(data);
}
else
{
Node<T>* temp = new Node<T>(data, head);
head->setPrev(temp);
head = temp;
}
size++;
}
...
The event container class:
class EventContainer
{
public:
EventContainer() :
events(List<BaseEvent*>()) {}
~EventContainer() {}
virtual void add(const BaseEvent&);
class EventIterator
{
public:
EventIterator() :
current(NULL) {}
EventIterator(Node<BaseEvent*>& node) :
current(&node) {}
EventIterator(Node<BaseEvent*>* node) :
current(node) {}
~EventIterator() {}
EventIterator& operator=(const EventIterator& nodeIterator) {
current = nodeIterator.current;
return *this;
}
EventIterator& operator++() {
current = current->getNext();
return *this;
}
BaseEvent& operator*() const {
return *(current->getValue());
}
friend bool operator==(const EventIterator& iterator1, const EventIterator& iterator2) {
return iterator1.current == iterator2.current;
}
bool operator!=(const EventIterator& iterator) const {
return !(*this == iterator);
}
private:
Node<BaseEvent*>* current;
};
virtual EventIterator begin() const;
virtual EventIterator end() const;
private:
List<BaseEvent*> events;
};
The implementation of add method:
void EventContainer::add(const BaseEvent& event) {
BaseEvent* eventClone = event.clone();
if (events.getSize() == 0)
{
events.insertStart(eventClone);
return;
}
Node<BaseEvent*>* current = events.getFirst();
while (current != NULL)
{
if (*eventClone < *(current->getValue()))
{
events.insertBefore(*current, eventClone);
return;
}
current = current->getNext();
}
events.insertLast(eventClone);
}
EventContainer::EventIterator EventContainer::begin() const {
return events.getFirst();
}
EventContainer::EventIterator EventContainer::end() const {
return NULL;
}
I have this code below, and I am having a hard time getting it to work (operators in the movable_ptr<T> class, to be precise).
//movable_ptr.hpp
//Michal Cermak
#ifndef MOVABLE_H
#define MOVABLE_H
template<typename T> class movable_ptr;
template<typename T> class enable_movable_ptr {
public:
//default constructor
enable_movable_ptr() : ptr_(nullptr) {};
enable_movable_ptr(T* p) : ptr_(p) {};
//copy
enable_movable_ptr(const enable_movable_ptr<T>&) {};
enable_movable_ptr& operator=(const enable_movable_ptr<T>& p) {
T* new_ptr = p.first_;
movable_ptr<T>* new_first = p.first_;
delete p;
ptr_ = new_ptr;
first_ = new_first;
return this;
};
//move
enable_movable_ptr(enable_movable_ptr<T>&& p) {};
enable_movable_ptr& operator=(enable_movable_ptr<T>&& p) {};
//destructor
~enable_movable_ptr() {delete ptr_; };
T* get() {return ptr_; };
movable_ptr<T>* getFirst() { return first_; };
void setFirst(movable_ptr<T>* p) { first_ = p; };
private:
T* ptr_ = nullptr;
movable_ptr<T>* first_ = nullptr;
};
template<typename T> class movable_ptr {
public:
//parameterless constructor
movable_ptr() {};
//constructor from T*
movable_ptr(T* p) : ptr_(p) { add_to_tracked(this); };
//copy
movable_ptr(const enable_movable_ptr<T>&) {};
movable_ptr& operator=(const enable_movable_ptr<T>& p) {};
//move
movable_ptr(enable_movable_ptr<T>&& p) {};
movable_ptr& operator=(enable_movable_ptr<T>&& p) {};
//destructor
~movable_ptr() {};
//operators
T& operator*() const { return ptr_; };
T* operator->() const { return ptr_; };
explicit operator bool() const noexcept { return ptr_ != nullptr; };
bool operator!() const { return ptr_ == nullptr; };
bool operator==(const movable_ptr<T>& p) const { return p.get() == ptr_; };
bool operator!=(const movable_ptr<T>& p) const { return p.get() != ptr_; };
//reset
void reset() noexcept { ptr_, next_, prev_ = nullptr; };
template<typename X> void reset(X* p) { remove_from_tracked(this); ptr_ = p; add_to_tracked(this); };
//access to variables
enable_movable_ptr<T>* get() {return ptr_; };
movable_ptr<T>* getNext() { return next_; };
void setNext(movable_ptr<T>* p) { next_ = p; };
movable_ptr<T>* getPrevious() {return prev_; };
void setPrevious(movable_ptr<T>* p) { prev_ = p; };
//get_movable
movable_ptr<T>* get_movable(enable_movable_ptr<T>& p) {};
private:
enable_movable_ptr<T>* ptr_ = nullptr;
movable_ptr<T>* next_ = nullptr;
movable_ptr<T>* prev_ = nullptr;
};
template<typename T> movable_ptr<T> get_movable(enable_movable_ptr<T>& p){
return new movable_ptr<p>(p);
};
//removes movable_ptr from tracked pointers
template<typename T> void remove_from_tracked(movable_ptr<T>* p) {
movable_ptr<T>* first = p->get()->getFirst();
movable_ptr<T>* prev = p->get()->getFirst()->getPrevious();
movable_ptr<T>* next = p->get()->getFirst()->getNext();
if (first == p && next != nullptr)
{
p->get()->setFirst(next);
}
if (prev != next)
{
next->setPrevious(prev);
prev->setNext(next);
}
else
{
next->setPrevious(nullptr);
prev->setNext(nullptr);
}
};
//adds movable_ptr to tracked pointers
template<typename T> void add_to_tracked(movable_ptr<T>* p) {
movable_ptr<T>* first = p->get()->getFirst();
movable_ptr<T>* prev = p->get()->getFirst()->getPrevious();
if (first != nullptr)
{
if (prev != nullptr) {
prev->setNext(p);
}
first->setPrevious(p);
}
p->get()->setFirst(p);
};
#endif
#include <memory>
#include <array>
#include "movable_ptr.hpp"
class MovableNode : public enable_movable_ptr<MovableNode>
{
public:
static const int MAX_REFS = 4;
using RefArray = std::array<movable_ptr<MovableNode>, MAX_REFS>;
MovableNode() : _isValid(false), _value(0), _refs() {}
MovableNode(int value) : _isValid(true), _value(value), _refs() {}
bool isValid() const { return _isValid; }
int value() const { checkValid(); return _value; }
RefArray& refs() { checkValid(); return _refs; }
private:
bool _isValid;
int _value;
RefArray _refs;
void checkValid() const;
};
The trouble is, the compiler is unable to convert the ptr_ variable to the correct return type in operator*. operator== and operator!= are in a similar situation, but this time it is the p.get() that cannot be converted from const movable_ptr<T> to movable_ptr<T> &, so that it can be properly compared.
Errors:
Error C2440 'return': cannot convert from 'enable_movable_ptr<MovableNode> *const ' to 'T &'
Error C2662 'enable_movable_ptr<A> *movable_ptr<T>::get(void)': cannot convert 'this' pointer from 'const movable_ptr<T>' to 'movable_ptr<T> &'
I am pretty sure I am just missing a minor detail, but how would I go about solving this?
Code that instantiates the classes:
#include <iostream>
#include <memory>
#include <string>
#include "movable_ptr.hpp"
using namespace std;
class A : public enable_movable_ptr<A>
{
public:
int val;
A(int val) : val(val) {}
};
void test_ptr_dereference() {
A x(42);
auto px = get_movable(x);
TEST_ASSERT(&*px == &x);
TEST_ASSERT(&px->val == &x.val);
}
int main(int argc, char* argv[]) {
test_ptr_dereference();
}
I'm writing codes about binary tree using smart pointer, but there is something wrong with destructor. I don't know where the momery leaks. But when I remove all components with parent pointer in BinNode, it runs with no errors.
Header file is showed as follow:
#ifndef BINARY_H
#define BINARY_H
#include <memory>
#include <iostream>
#ifndef RANK_DEFINED
#define RANK_DEFINED
typedef int64_t Rank;
#endif
template <typename T> class BinaryTree;
typedef enum {RB_RED, RB_BLACK} RBColor;
template <typename T>
class BinNode {
public:
friend class BinaryTree<T>;
BinNode() = default;
BinNode(const T& data, std::shared_ptr<BinNode> pare = nullptr, std::shared_ptr<BinNode> left = nullptr, std::shared_ptr<BinNode> right = nullptr,
int h = 1) : _data(data), left_child(left), right_child(right), parent(pare), height(h){}
~BinNode() = default;
std::shared_ptr<BinNode> insertAsLeft(const T& e) {
left_child = std::make_shared<BinNode>(e);
left_child->parent = std::shared_ptr<BinNode>(this);
return left_child;
}
std::shared_ptr<BinNode> insertAsRight(const T& e) {
right_child = std::make_shared<BinNode>(e, this);
return right_child;
}
int size() const;
std::shared_ptr<BinNode> succ();
template <typename VST> void travelLevel(VST (*f)());
template <typename VST> void travelPre(VST (*f)());
template <typename VST> void travelIn(VST&);
template <typename VST> void travelPost(VST&);
bool operator<(BinNode const& bn) { return _data < bn._data; }
bool operator==(BinNode const& bn) { return _data == bn._data; }
bool isRoot() { return !(parent); }
bool isLChild() { return !isRoot() && this == parent->left_child; }
bool isRChild() { return !isRoot() && this == parent->right_child; }
bool hasParent() { return !isRoot(); }
bool hasLChild() { return !left_child; }
bool hasRChild() { return !right_child; }
bool hasChild() { return hasLChild() || hasRChild(); }
bool hasBothChild() { return hasLChild() && hasRChild(); }
bool isLeaf() { return !hasChild(); }
std::shared_ptr<BinNode> sibling() const {
return (isLChild() ? parent->right_child : parent->left_child);
}
std::shared_ptr<BinNode> uncle() const {
return parent->sibling();
}
private:
T _data;
std::shared_ptr<BinNode<T>> left_child = nullptr;
std::shared_ptr<BinNode<T>> right_child = nullptr;
std::shared_ptr<BinNode<T>> parent = nullptr;
int height = 1;
};
// Binary Tree Defination
template <typename T>
class BinaryTree
{
using BN = BinNode<T>;
public:
BinaryTree(): _size(0), _root(nullptr) {}
~BinaryTree() = default;
int size() const { return _size; }
bool empty() const { return !_root; }
std::shared_ptr<BN> root() const { return _root; }
std::shared_ptr<BN> insertAsRoot(const T& e);
std::shared_ptr<BN> insertAsLC(std::shared_ptr<BN> pare, const T& e);
std::shared_ptr<BN> insertAsRC(std::shared_ptr<BN> pare, const T& e);
std::shared_ptr<BN> insertAsLC(std::shared_ptr<BN> pare, BinaryTree<T> bt);
std::shared_ptr<BN> insertAsRC(std::shared_ptr<BN> pare, BinaryTree<T> bt);
int remove(std::shared_ptr<BN>);
BinaryTree* secede(std::shared_ptr<BN>);
template <typename VST>
void travelLevel(VST& visit) { if (_root) _root->travelLevel(visit); }
template <typename VST>
void travelPre(VST& visit) { if (_root) _root->travelPre(visit); }
template <typename VST>
void travelIn(VST& visit) { if (_root) _root->travelIn(visit); }
template <typename VST>
void travelPost(VST& visit) { if (_root) _root->travelPost(visit); }
protected:
Rank _size;
std::shared_ptr<BN> _root;
virtual int updateHeight(std::shared_ptr<BN>);
void updateHeightAbove(std::shared_ptr<BN>);
void delTree(std::shared_ptr<BN>);
};
template <typename T>
std::shared_ptr<BinNode<T>> BinaryTree<T>::insertAsRoot(const T& e)
{
_root = std::make_shared<BN>(e);
_size = 1;
return _root;
}
template <typename T>
std::shared_ptr<BinNode<T>> BinaryTree<T>::insertAsLC(std::shared_ptr<BN> pare, const T& e)
{
auto newNode = pare->insertAsLeft(e);
_size++;
updateHeightAbove(newNode);
return pare->left_child;
}
template <typename T>
std::shared_ptr<BinNode<T>> BinaryTree<T>::insertAsRC(std::shared_ptr<BN> pare, const T& e)
{
}
template <typename T>
void BinaryTree<T>::updateHeightAbove(std::shared_ptr<BN> x)
{
while(x)
{
updateHeight(x);
x = x->parent;
}
}
template <typename T>
int BinaryTree<T>::updateHeight(std::shared_ptr<BN> x)
{
Rank lh = 1, rh = 1;
if (x->left_child)
lh = x->left_child->height;
if (x->right_child)
rh = x->right_child->height;
x->height = (lh > rh) ? lh : rh;
return x->height;
}
#endif
and main function is:
int main()
{
BinaryTree<int> bt;
bt.insertAsRoot(1);
bt.insertAsLC(bt.root(), 2);
cout << bt.size() << endl;
return 0;
}
Result is double free or corruption (out).
There are two problems with your parent links:
Both the downwards and the upwards pointers are std::shared_ptr. This is known as a reference cycle and prohibits your tree from ever being destroyed properly. A common solution is to make the parent pointer a std::weak_ptr, such that it does not count towards keeping the parent alive.
The second problem is hidden in your insertAsLeft: std::shared_ptr<BinNode>(this) will construct a new shared_ptr with refcount 1. This means that you have multiple shared_ptrs pointing to the same block of memory and the first one that drops to refcount 0 frees the block, leaving you with dangling pointers. Luckily for you, C++ has a ready-made solution. Simply inherit from std::enable_shared_from_this and use left_child->parent = shared_from_this(); instead. In a nutshell, this construction allows BinNode to keep track of which shared_ptr owns it.
Got this error messege on an attempt to return the data from an Item template under iterator class.
I don't understand why Im getting an error (C++)..
template<class E>
class Item {
Item<E>* next;
E data;
public:
Item() :next(NULL) {}
Item(const E& pdata) :next(NULL), data(pdata) {}
void setNext(Item<E>& next) { this->next = next; }
Item<E>& getNext() { return next; }
void setData(const E pdata) { this->data = data; }
E& getData() { return data; }
};
this is the iterator class:
class Iterator {
Item<T>* p;
public:
Iterator(Item<T>* pt = NULL) :p(pt) {}
Iterator& operator++(int) {
p = p->getNext();
return *this;
}
T& operator*() { return *(p->getData()); }
friend class RoundList<T>;
};
they're both under a template class that called RoundList (template )
help...?
This is the code I tested.
template <class E>
class Item {
Item<E>* next;
E data;
public:
Item() :next(NULL) {}
Item(const E& pdata) :next(NULL), data(pdata) {}
void setNext(Item<E>& next) { this->next = next; }
Item<E>& getNext() { return next; }
void setData(const E pdata) { this->data = pdata; }
E& getData() { return data; }
};
template <class T>
class Iterator {
Item<T>* p;
public:
Iterator(Item<T>* pt = NULL) :p(pt) {}
Iterator& operator++(int) {
p = p->getNext();
return *this;
}
T& operator*() { return p->getData(); }
};
int main()
{
Item<int>* test = new Item<int>();
Iterator<int>* iterTest = new Iterator<int>(test);
test->setData(2);
cout << iterTest->operator*() << endl;
cout << (test->getData() = 4) << endl;
}
I'm not sure how you want to use your Iterator, but I tried with a simple type, like int and it works. Anyway I change your *(p->getData()) in p->getData() since in getData you are already returning a reference.