I am building a linked list, where nodes are all linked to Head. The Head is derived from node, but the Head requires a pointer to last node. See the comment at the top of code.
/* Base <= node <= node <= node
* | ^
* | ptr to last node |
* -------------------------
*/
class Node {
private:
Node* prev;
public:
explicit Node(Node* parent) : prev(parent) {
Node* foo_ptr = this;
while (foo_ptr->prev != 0) {
foo_ptr = foo_ptr->prev;
}
// foo_ptr points to Base, how can I now change Base::last?
}
};
class Base : public Node {
private:
Node* last;
public:
Base() : Node(0), last(this) {}
};
How can I change change variable Base::last when adding new node, for example:
Node* n = new Base;
new Node(n); // can Node constructor update n->last?
I was thinking to use virtual function to update the variable, but according to this post: Calling virtual functions inside constructors, its a no no so I do not want to do it. So is there a good way of achieving this type of linked list?
Thanks...
http://coliru.stacked-crooked.com/a/213596aa1ffe7602
I added a flag value so we can tell that we actually accessed the Base class:
#include <iostream>
class Node {
private:
Node* prev;
public:
inline void changeBaseLast(Node* base);
explicit Node(Node* parent) : prev(parent) {
Node* foo_ptr = this;
while (foo_ptr->prev != 0) {
foo_ptr = foo_ptr->prev;
}
// foo_ptr points to Base
// now change Base::last
changeBaseLast(foo_ptr);
}
int data;
};
class Base : public Node {
private:
Node* last;
public:
int flag;
Base() : Node(0), last(this), flag(0) {}
};
//Here, we can see that we change the base_ptr to 1.
void Node::changeBaseLast(Node* base) {
Base* base_ptr = static_cast<Base*>(base);
base_ptr->flag=1;
}
int main() {
Node* n = new Base;
new Node(n);
std::cout << static_cast<Base*>(n)->flag << std::endl;
}
If you pull out the part that refers to the derived class and then inline it, there should be no problems with this. Notice, though, that I need to define the functions that refer to the derived class after I define the derived class.
If you're sure that the last node will always be a Base object, then using static_cast<Base*> may not be that bad.
class Base : public Node {
...
// Factory method to create child nodes
Node* getNode(Node* parent) {
Node* newNode = new Node(parent);
last = newNode;
return newNode;
}
}
This one should be even easier to understand and still uses static_cast, for you want to append by means of the Base class.
class Node {
private:
Node* prev;
public:
explicit Node() : prev{nullptr} { }
void setParent(Node *parent) {
prev = parent;
}
};
class Base : public Node {
private:
Node* last;
public:
Base() : Node{}, last{this} { }
void append(Node *node) {
node->setParent(last);
last = node;
}
};
int main() {
Node* n = new Base;
static_cast<Base*>(n)->append(new Node{});
}
Anyway, I don't understand the need of the Base class.
Can't you simply store somewhere (as an example a struct) two pointers, one for the head of the list and one for the last node?
Related
class LinkedList : public IDataList {
public :
Node *head;
Node* lastNode;
int _size = 0;
public : LinkedList() {
this->head = nullptr;
this->lastNode = nullptr;
}
void deAppend(int data) override;
};
Then I have a circular linkedList which is the subclass of LinkedList
class CircularLinkedList : public LinkedList {
public :
Node *head;
Node* lastNode;
int _size = 0;
public : CircularLinkedList() {
this->head = nullptr;
this->lastNode = nullptr;
}
void deAppend(int data) override;
};
This is the method deAppend which adds to the front of the list
void LinkedList::deAppend(int data){
if (this->head== nullptr){
Node *newNode = new Node(data, nullptr);
this->head = newNode;
this->lastNode = newNode;
}else{
Node *newNode = new Node(data, this->head);
this->head = newNode;
}
this->_size+=1;
}
This is my CiruclarLinkedList calling deAppend method
void CircularLinkedList::deAppend(int data) {
LinkedList::deAppend(data);
this->lastNode->next = this->head;
}
The fact is why doesn't the lastNode and the head of CircularLinkedList variables change even though I am calling the method LinkedList::deAppend(data) and changing them in there. IDataList is just an interface.
class IDataList {
public:
virtual void deAppend(int data) = 0;
};
Picture of Variables assignments after the method is called
I think you are declaring your variables twice. I mean inside your base class you declare:
public:
Node *head;
Node* lastNode;
int _size = 0;
When a class inherits from another class publicly, all the public variables of the base class are also declared in the sub class. Which means you already had these variables in your CircularLinkedList class but you declared them again. Now you have two of them and you're changing the ones from your base class. remove the declaration from CircularLinkedList.
How to correctly delete base class elements
base class:
class node
{
private:
node *left, *right, *parent;
public:
node(node* parent,node* left,node* right);
};
subclass:
class nodeFunc: public node
{
private:
int x;
public:
nodeFunc(int x, node* parent, node* left, node* right);
};
class, which contains vector:
class tree
{
private:
vector<node*> nodes;
public:
tree(int size);
~tree();
};
in constructor:
tree::tree(int size)
{
for (int i = 0; i < size; i++)
nodes.push_back( new nodeFunc(i,NULL,NULL,NULL) );
}
destructor:
tree::~tree()
{
for (vector<node*>::iterator it=nodes.begin();it!=nodes.end();++it)
{
delete (*it);
}
nodes.clear();
}
in main.cpp:
int main()
{
tree* myTree = new tree(10);
delete myTree;
cout<<"end"<<endl;
}
I use debugger to see what happened in every line. After first, myTree->nodes contains 10 elements. After delete myTree->nodes contains 58 items.
After the line delete myTree;, the pointer myTree becomes invalid, because it points to deallocated memory. You cannot dereference it.
As for deleting base class objects, you just need to implement a virtual desctructor in the base class: virtual ~node( );.
I watched a video that can be found at
https://www.youtube.com/watch?v=4F72VULWFvc and I really liked some of the concept for the cases that presented. But I am working with linked list and need selective method execution, for example:
#include <stdio.h>
class A {
public:
A() : next(0) {
if (head == 0) {
head = this;
} else {
A* step = head;
while (step->next != 0) {
step = step->next;
}
step->next = this;
}
}
virtual ~A() {
if (head == this) {
head = 0;
} else {
A* step = head;
while (step->next != this) {
step = step->next;
}
step->next = next;
}
}
virtual void foo() {
// Do nothing...
}
static A* head;
A* next;
};
class B : public A {
public:
B() {}
virtual ~B() {}
virtual void foo() {
printf("function foo\n");
}
};
A* A::head = 0;
int main() {
A a_cls;
B b_cls;
A* step = A::head;
while (step != 0) {
step->foo();
step = step->next;
}
return 0;
}
After instantiating all of the objects, the method foo() of objects of class B need to execute. To achieve this, virtual method foo() is added to class A, with empty body, virtual void foo() {}, and in class B, code is added to the method foo() body.
It works but I do not like it, in the main function it looks like you are doing something at each node, but you are not, it almost feels like a NULL pointer. Is there another creative solution for this?
Note: I am using C++03.
Check out dynamic_cast as a way to check for a particular derived type and only call foo on objects of class B (or a class derived from B):
int main() {
A a_cls;
B b_cls;
A* step = A::head;
B* step_b = 0;
while (step != 0) {
step_b = dynamic_cast<B *>(step);
if (step_b != 0) {
step_b->foo();
}
step = step->next;
}
return 0;
}
This way, there's no need to define an empty foo method on A. Try it out on ideone.
It works but I do not like it, in the main function it looks like you
are doing something at each node, but you are not
In fact you are doing something at each node. What you are doing is the decision to do nothing. Decisions are generally not free and you haven't told us enough about the application to justify the guess that it could be restructured in a way that the decision could be effectively free (made at compile time).
If the decision to do nothing can't be free, then implementing that decision as a call to a virtual function is nearly as low in cost as that decision could possibly be.
It works but I do not like it, in the main function it looks like you are doing something at each node, but you are not, it almost feels like a NULL pointer. Is there another creative solution for this?
Make sure that your base class is a pure abstract class. That way, every call to step->foo(); will most likely do something.
Here's a bare bones example of a heterogeneous list. List::Node is an abstract base class. List::Node::print() is a virtual member function that is implemented only in the concrete classes. List is able to use a generic algorithm to step through the Nodes without having explicit knowledge of the kinds of Nodes it contains.
#include <iostream>
#include <string>
class List
{
public:
class Node
{
public:
Node() : next(nullptr) {}
virtual ~Node() {}
virtual void print() = 0;
Node* next;
};
List() : head(nullptr), tail(nullptr) {}
~List()
{
Node* node = head;
Node* next = nullptr;
for ( ; node != nullptr; node = next )
{
next = node->next;
delete node;
}
}
void addNode(Node* node)
{
if (head == 0)
{
head = tail = node;
return;
}
if ( head == tail )
{
head->next = node;
}
tail->next = node;
tail = node;
}
void print()
{
Node* node = head;
for ( ; node != nullptr; node = node->next )
{
node->print();
std::cout << std::endl;
}
}
Node* head;
Node* tail;
};
class NodeA : public List::Node
{
public:
NodeA(int d) : data(d) {}
virtual ~NodeA() {}
virtual void print()
{
std::cout << "In NodeA::print(), Data: " << data;
}
private:
int data;
};
class NodeB : public List::Node
{
public:
NodeB(double d) : data(d) {}
virtual ~NodeB() {}
virtual void print()
{
std::cout << "In NodeB::print(), Data: " << data;
}
private:
double data;
};
class NodeC : public List::Node
{
public:
NodeC(std::string const& d) : data(d) {}
virtual ~NodeC() {}
virtual void print()
{
std::cout << "In NodeC::print(), Data: " << data;
}
private:
std::string data;
};
int main()
{
List list;
list.addNode(new NodeA(10));
list.addNode(new NodeB(23.45));
list.addNode(new NodeC("abcd"));
list.print();
return 0;
}
Although Austin's solution is perfectly fine, another approach (that I typically prefer) in such situations is to use interface classes and upcasting.
class FooFighter { public: virtual void foo() = 0; };
class A { ... };
class B1 : public A { ... };
class B2 : public A, public FooFighter { ... };
...
int main() {
std::vector<A *> v;
// fill up v
for (int i = 0; i < v.size(); ++i) {
FooFighter * ff = dynamic_cast<FooFighter *>(v[i]);
if (ff) ff.foo();
}
return 0;
}
This lets you keep whether or not a class has foo independent of the rest of your hierarchy. In particular, by examining the class hierarchy of any type you always know whether or not that type implements foo, because it has to inherit from FooFighter. When you use the downcasting approach, you could have multiple children of A that non-trivially implement foo in different ways. This approach also meshes extremely well with IDEs that let you easily examine and traverse the type hierarchies in your code.
I have this tree with different types of nodes that I need to do a deep copy on. The hierarchy looks something like this:
class AllNodes
{
//this is a purely virtual base class
};
class TreeNode : public AllNodes
{
AllNodes *rChild, *lChild;
};
class LeefNode : public AllNodes
{
int value;
};
The problem is that when I want to do a deep copy of the entire tree, I don't know what nodes will have children and what nodes will have values. I've tried this, but it wont work (for obvious reasons):
void AllNodes::deepCopy(AllNodes* &copied, AllNodes* o)
{
if(o->rChild == nullptr)
copied->rChild = nullptr;
else
{
copied->rChild = o->rChild;
deepCopy(copied->rchild, o->rChild);
}
if(o->lChild == nullptr)
copied->lChild = nullptr;
else
{
copied->lChild = o->lChild;
deepCopy(copied->lChild, o->lChild);
}
}
Does anyone have some ideas of how to accomplish this?
Create a virtual method and implement it in TreeNode and LeafNode.
class AllNodes
{
//this is a purely virtual base class
virtual AllNodes* copy() const = 0;
};
class TreeNode : public AllNodes
{
AllNodes* rChild, lChild;
virtual AllNodes* copy() const {
TreeNode *n = new TreeNode;
n->rChild = rChild->copy();
n->lChild = lChild->copy();
return n;
}
};
class LeafNode : public AllNodes
{
int value;
virtual AllNodes* copy() const {
LeafNode *n = new LeafNode;
n->value = value;
return n;
}
};
(Just a draft)
This is polymorphic behavior (creating a deep copy, based on the concrete type of the object). As such, it should be implemented in a virtual function, accross the entire nodes hierarchy.
The function to perform the deep copy is usually called clone:
class AllNodes
{
//this is a purely virtual base class
public:
virtual AllNodes* clone() = 0;
};
class TreeNode : public AllNodes
{
AllNodes *rChild, *lChild; // you skipped declaring lChild as a pointer
public:
virtual AllNodes* clone() override // recursive implementation for child nodes
{
return new TreeNode{
rChild ? rChild->clone() : nullptr,
lChild ? lChild->clone() : nullptr }; // assume existence of this
// constructor
}
};
class LeafNode : public AllNodes
{
int value;
public:
virtual AllNodes* clone() override
{
return new LeafNode{ value }; // assume existence of this constructor
}
};
Client code (deep copy of the entire tree):
AllNodes *original; // filled in elsewhere
AllNodes *deepCopy = original->clone();
I have
class A{
}
class B : virtual public A{
extra property 1
}
class C : virtual public A{
extra property 2
}
class D : virtual public A{
}
class E : virtual public B, virtual public C, virtual public D{
extra property 3
}
And here's my linked list's insert function:
template <typename T>
class LinkedList {
Node<T> *start;
Node<T> *current;
public:
void insert (T newElement)
{
if ( isEmpty() )
{
insertToStart(newElement);
}
else
{
Node<T> *newNode = new Node<T>;
newNode->info = newElement;
newNode->next = NULL;
current = start;
while (current->next != NULL)
{
current = current->next;
}
current->next = newNode;
}
}
Now I would like to create a single linked list that will store all instances of B, C and D without losing the additional attribute of each child class. How can I achieve this using pointer?
I've tried the solution provided here, but it gives me this error: taking address of temporary [-fpermissive].
Linkedlist<A*> list;
B b;
list.insert(&b);
The following piece of code compiles fine with gcc 4.8:
#include <list>
class A
{
};
class B : virtual public A
{
};
int main()
{
std::list<A*> l;
B* b = new B();
l.push_back(b);
B bb;
l.push_back(&bb);
return 0;
}