Value from default field initialization is not being assigned - c++

I'm currently working on a lab for my operating systems class and I'm having trouble understanding why the value I specify in a class' default field initialization is not being assigned. I have the following scheduler class:
class LOOK : SSTF {
public:
io_req* pop() override;
};
That inherits from this scheduler:
class SSTF : protected IOSched {
public:
virtual io_req* pop() override;
virtual void push(io_req* new_req) override;
protected:
io_req* left_pop();
io_req* right_pop();
int dir;
LinkedList left;
LinkedList right;
};
Where IOSched is a pure virtual class with the pop() and push() methods and a curr_req field, and this is the LinkedList class:
class LinkedList {
public:
io_req* pop();
void push(io_req* new_req);
void push_in_order(io_req* new_req);
io_req* top() const;
void reset_dist(io_req* new_curr);
private:
void insert_between(io_req_node* new_prev, io_req_node* new_next, io_req_node* new_node);
io_req_node* head = nullptr;
io_req_node* tail = nullptr;
};
From my understanding of C++, when I allocate a new LOOK object as such:
sched = (IOSched*)(new LOOK());
I will get a pointer to a heap-allocated LOOK object which will contain an SSTF object, which will contain two LinkedList objects, left and right, which will be initialized with head and tail as nullptr.
However, for some reason I am getting a value of 0x203d1 for left.head while 0x0 for the rest. This only happens when sched is initialized as a LOOK object and not when it SSTF (for the lab I have to implement a few different algorithms).
Thanks in advance!

sched = (IOSched*)(new LOOK());
You cannot cast a pointer to a protected base class outside of the class:
class A{};
class B : protected A {
void foo(){
B b;
A * a = &b; // this is ok
}
};
int main() {
A * a = new B; // this is not
}
Use public inheritance instead - that's almost always what you want in a traditional object-oriented situation.
Also, don't use c-style casts in c++. If you used static_cast, it would have continued to yell at you as you deserved to be yelled at :)

Non-static member initialisation is an extension of C++11 (see here).
Since your members are not static, you have to initialize them in the constructor initialisation list:
class LinkedList {
public:
LinkedList() : head(nullptr), tail(nullptr) {}
io_req* pop();
void push(io_req* new_req);
void push_in_order(io_req* new_req);
io_req* top() const;
void reset_dist(io_req* new_curr);
private:
void insert_between(io_req_node* new_prev, io_req_node* new_next, io_req_node* new_node);
io_req_node* head ; // useless = nullptr;
io_req_node* tail , // useless = nullptr;
};
Or switch to C++11 or higher.

Related

Alternative to virtual templated function

I currently use a tree structure, made out of subtypes of the class Node. The base Node class looks something like this:
// Base Node Type
class Node
{
public:
virtual ~Node() = default;
virtual std::vector<Node*> GetChildren() const = 0;
};
Here are some example Node subtypes:
// First Node Subtype
class NodeOne : public Node
{
public:
NodeOne(std::unique_ptr<Node>&& t_node)
: m_Node{ std::move(t_node) }
{
}
virtual ~NodeOne() = default;
std::vector<Node*> GetChildren() const override
{
std::vector<Node*> children{};
AddChildren(children, m_Node);
return children;
}
private:
std::unique_ptr<Node> m_Node{};
};
This node owns a pointer to another child Node (can be null).
// Second Node Subtype
class NodeTwo : public Node
{
public:
NodeTwo(std::unique_ptr<NodeOne>&& t_leftNode, std::unique_ptr<NodeOne>&& t_rightNode)
: m_LeftNode{ std::move(t_leftNode) }, m_RightNode{ std::move(t_rightNode) }
{
}
virtual ~NodeTwo() = default;
std::vector<Node*> GetChildren() const override
{
std::vector<Node*> children{};
AddChildren(children, m_LeftNode);
AddChildren(children, m_RightNode);
return children;
}
private:
std::unique_ptr<NodeOne> m_LeftNode{};
std::unique_ptr<NodeOne> m_RightNode{};
};
This node owns a pointer to two child NodeOnes (both can be null). As you can see, both implement the pure virtual function GetChildren(). This is the implementation of the AddChildren() function (it just adds the Node* and its Node* children to the std::vector<Node*>):
// AddChildren() Implementation
template<typename T>
void AddChildren(std::vector<Node*>& t_vec, const std::unique_ptr<T>& t_child)
{
if (!t_child)
return;
auto children{ t_child->GetChildren() };
t_vec.insert(t_vec.end(), children.begin(), children.end());
t_vec.push_back(t_child.get());
}
I recently noticed, getting children of all Node subtypes from GetChildren() is not what I actually want most of the time. I often need children of just one specific interface or type. I wanted to achieve this by making the GetChildren() function a template<>, and then in AddChildren() I would only add a Node* to the std::vector<Node*> if it is of that type (with a constexpr if statement or something similiar). I just found out that template<> on a virtual function is not allowed in C++. Is there any way I could GetChildren() of only one type (I don't want to use RTTI so I would prefer a compile time solution).

Calling parent function from another function using child C++

So I have a parent Class which is:
class Node
{
public:
Node();
void setParentNode(Node* parent) {this->parentNode = parent;}
Node* getParentNode() {return this->parentNode;}
std::vector<Node> getChildNodes(){return this->childNodes;}
void addChildNode(Node* node);
void removeNode();
private:
std::vector<Node*> childNodes;
Node* parentNode = nullptr;
};
And a child inheriting from that class:
class Cube : public Node
{
public:
Cube();
};
Now I have another file which has a function that uses the child class:
#include "cube.h"
void addCubes(){
Cube mainCube;
for(int i = 0; i < 10; i++){
Cube c;
mainCube.addChildNode(c);
}
}
Problem is that mainCube doesn't see the addChildNode function which the parent has. What is the point of inheriting from another class if the parents functions aren't accessible from another place using the child class?
No, the parent classes public functions are callable from the child object.
However, the prototype of the function is
void Node::addChildNode(Node node);
So it's taking a Node object & not a Cube object.
So your compiler cannot find a function which takes a Cube object & hence the error.
The fix is to use a pointer to Node or reference to Node while declaring/defining the function.
So you function should be
void addChildNode(Node & node);
In which case, the Node object can be passed to the function & the compiler will find it.
Even better would be to have
// if you aren't looking to modify the passed object inside addChildNode
void addChildNode(const Node & node);
The following is fine & hence the function will work
Cube b;
Node &a = b;
or
Node * pn = &b;
The derived classes should be able to see the addChildNode function if you keep the signature of the function aligns. This is not a big issue. However, there are a few more "serious" issues with your code:
You need to make the base class' destructor virtual to avoid some undefined behaviors.
You have to design the ownership of nodes carefully. I guess you want the Node class to own and manage its children nodes. That means function addChildNode actually takes the ownership of the passed in node object, and it should also be deleted during destruction.
In function addCubes(), there is a loop that keeps calling addChildNode function but passes the local variable Cube c; which will be out of scope and destroyed after the loop. Thus, the parent object mainCube will holds pointers to already destroyed objects, and it will cause a crash.
After fixing all these issues, your code looks like this:
class Node
{
public:
Node() {};
virtual ~Node() {
for(auto n: childNodes) delete n;
};
void setParentNode(Node* parent) {this->parentNode = parent;}
Node* getParentNode() {return this->parentNode;}
std::vector<Node*> getChildNodes(){return this->childNodes;}
void addChildNode(Node* node) {
childNodes.push_back(node);
};
void removeNode();
private:
std::vector<Node*> childNodes;
Node* parentNode = nullptr;
};
class Cube : public Node
{
public:
Cube() {};
};
void addCubes(){
Cube mainCube;
for(int i = 0; i < 10; i++){
Cube *c = new Cube();
mainCube.addChildNode(c);
}
}
It is preferred to use smart pointers to manage memory, and the code is more elegant and easier to read, and it makes it harder to make mistakes :-).
#include <memory>
class Node
{
public:
Node() {};
virtual ~Node() {};
void setParentNode(Node* parent) {this->parentNode = parent;}
Node* getParentNode() {return this->parentNode;}
std::vector<std::shared_ptr<Node>>& getChildNodes(){return this->childNodes;}
void addChildNode(std::shared_ptr<Node> node) {
childNodes.push_back(std::move(node));
};
void removeNode();
private:
// childNodes own elements in it, they will be deleted automatically.
std::vector<std::shared_ptr<Node>> childNodes;
Node* parentNode = nullptr;
};
class Cube: public Node
{
public:
Cube() {};
};
void addCubes(){
Cube mainCube;
for(int i = 0; i < 10; i++){
auto c = std::make_unique<Cube>();
mainCube.addChildNode(std::move(c));
}
}
Assuming that you have shared the entire implementation of your code. You have not defined the body of the function addChildNode, similar to setParentNode etc. You need to do something like childNodes.push_back(node); inside that function.
Note: It is also necessary that you pass the input to addChildNode as shown in the answer by #user93353. Also, define childNodes as std::vector<Node *> in order to avoid object slicing.

Too few arguments inheritance c++

I'm working on learning inheritance by making a generic List class. List can be an Unordered list, an Ordered list, a Stack, or a Queue.
My List class looks like this:
class List
{
public:
class Node
{
public:
int data;
Node * next;
Node(int data);
};
int sizeOfList = 0;
Node * head = nullptr;
List::List();
virtual void get(int pos);
virtual void insert(int data);
virtual void remove(int pos);
virtual void list();
virtual int size();
};
My Unordered list class looks like this:
class UnOrderedList : public List
{
public:
UnOrderedList();
void get();
void insert(int data);
virtual void remove(); //takes no parameters because first item is always removed
};
In main(), I create an array of Lists like this;
List * lists[8];
and make an Unordered list like this:
lists[0] = new UnOrderedList();
My question:
lists[listNum]->get(); gives error
"too few arguments in function call"
because it thinks I am trying to call get() in the Listclass, but I want it to call the Unordered list's function get().
I feel I must improve upon Sam Varshachik's answer - though he is totally correct.
class List
{
public:
virtual void get(int pos);
};
class UnOrderedList : public List
{
public:
void get();
};
Note that there are two problems here - not just one.
Firstly the signature of get(int) is different from get() - these are two different methods, and the compiler will treat them as such.
Further you have declared that the method List::get(int) be virtual, but you have not done-so for UnOrderedList::get() - Remember that the list object has no knowledge about it's children - Thus a list * cannot understand the details of UnOrderedList.
Consider this example:
class List
{
public:
virtual void get(int pos);
};
class UnOrderedList : public List
{
public:
virtual void get(); //STILL AN ERROR!
};
In this case, I have made UnOrderedList::get() virtual - However this won't help. As list still has no knowledge of this method.
The correct snippet is as follows:
class List
{
public:
virtual void get(int pos);
virtual void get();
};
class UnOrderedList : public List
{
public:
virtual void get(); //We can use this now!
virtual void get(int pos); //This is only needed if we intend to override this method
};
In this example list::get() is now a virtual method - as such any call to it will be communicated to the correct-child as you intended.
This is only possible however because the parent class has been informed that such a method exists, and can be over-ridden by the child classes.
[edit /]
As JonathanPotter stated in the comments, pay attention to the fact that the virtual keyword is only needed if you wish for a method called from a parent-pointer to be routed to the actual child object. And that this does incur some overhead.
You need declare get() as a virtual method in the List class. Either that, or dynamic_cast it.
When you invoke get() using a pointer to a List, that particular pointer can point to any subclass of List. Just because one particular subclass of List implements a particular method doesn't mean that you can invoke it directly using a pointer to the base class.
Otherwise, there's no point to have base classes. And this is exactly what virtual methods are for: to allow you to invoke the methods in a subclass, using a pointer to the base class.
lists[0] is a List* as far as the compiler's concerned.
UnOrderedList::get() won't override List::get(int pos) because the signatures are different. If you want the derived class to override a function in the base class the function signatures have to be the same.
As it is, you would need to cast lists[listNum] to UnOrderedList* to call UnOrderedList::get(), e.g. static_cast<UnOrderedList*>(lists[listNum])->get().

Remove dynamic_cast in derived class of tree node

I have a class which is a node of a tree, called Node. I need to create a DerivedNode class type which has some extra functionality. The problem is that Node has a vector of Node* as a member variable, so when DerivedNode inherits from Node, it inherits this vector. I've created a basic example showing the issue:
#include <iostream>
#include <vector>
class Node {
public:
Node(int value_) : value(value_) {}
int foo() { return value; }
virtual void add(Node* new_node) {
children.push_back(new_node);
}
protected:
std::vector<Node*> children;
int value;
};
class DerivedNode : public Node {
public:
DerivedNode(int value_) : Node(value_) {}
int bar() { return value*2; }
// Ensures we only add children of type DynamicNode*
virtual void add(DerivedNode* new_node) {
children.push_back(new_node);
}
void print() {
for (size_t i = 0; i < children.size(); ++i) {
std::cout << dynamic_cast<DerivedNode*>(children[i])->bar() << std::endl;
}
}
};
int main() {
DerivedNode* child_a = new DerivedNode(5);
DerivedNode* child_b = new DerivedNode(6);
DerivedNode parent(1);
parent.add(child_a);
parent.add(child_b);
parent.print();
delete child_a;
delete child_b;
}
My question is, how can I do this without the dynamic_cast? My actual code is far more complex which means that there are dynamic casts everywhere.
First add function in derived class is totally useless, it does not override add function from base class, it overloads it. In such way you still can add Node*'s to the derived class. To prevent this you should override add(Node*) as private.
If you does not like dynamic cast, you may use static cast instead
or
You may have virtual bar in base class that does not do anything
or
you can cast the vector itself (the whole thing) and assign to reference or pointer to std::vector DerivedNode*
You can't have it both ways. You either have IS-A principle reflected in the design of your classess, or you don't. If DerivedNode is Node, than the vector of Nodes should be indistinguishable from vector of DerivedNodes - and no casts are neccessary. If this can not be achieved, that you simply can not use vector of base pointers.
Any dynamic_cast in production code for me is a hard block for any review, as it clearly violates the basic design principles.

Null Object Pattern, Recursive Class, and Forward Declarations

I'm interested in doing something like the following to adhere to a Null Object design pattern and to avoid prolific NULL tests:
class Node;
Node* NullNode;
class Node {
public:
Node(Node *l=NullNode, Node *r=NullNode) : left(l), right(r) {};
private:
Node *left, *right;
};
NullNode = new Node();
Of course, as written, NullNode has different memory locations before and after the Node class declaration. You could do this without the forward declaration, if you didn't want to have default arguments (i.e., remove Node *r=NullNode).
Another option would use some inheritence: make a parent class (Node) with two children (NullNode and FullNode). Then the node example above would be the code for FullNode and the NullNode in the code above would be of type NullNode inheriting from Node. I hate solving simple problems by appeals to inheritence.
So, the question is: how do you apply Null Object patterns to recursive data structures (classes) with default arguments (which are instances of that same class!) in C++?
Use extern:
extern Node* NullNode;
...
Node* NullNode = new Node();
Better yet, make it a static member:
class Node {
public:
static Node* Null;
Node(Node *l=Null, Node *r=Null) : left(l), right(r) {};
private:
Node *left, *right;
};
Node* Node::Null = new Node();
That said, in both existing code, and amendments above, you leak an instance of Node. You could use auto_ptr, but that would be dangerous because of uncertain order of destruction of globals and statics (a destructor of some global may need Node::Null, and it may or may not be already gone by then).
I've actually implemented a recursive tree (for JSON, etc.) doing something like this. Basically, your base class becomes the "NULL" implementation, and its interface is the union of all interfaces for the derived. You then have derived classes that implement the pieces- "DataNode" implements data getters and setters, etc.
That way, you can program to the base class interface and save yourself A LOT of pain. You set up the base implementation to do all the boilerplate logic for you, e.g.
class Node {
public:
Node() {}
virtual ~Node() {}
virtual string OutputAsINI() const { return ""; }
};
class DataNode {
private:
string myName;
string myData;
public:
DataNode(const string& name, const string& val);
~DataNode() {}
string OutputAsINI() const { string out = myName + " = " + myData; return out; }
};
This way I don't have to test anything- I just blindly call "OutputAsINI()". Similar logic for your whole interface will make most of the null tests go away.
Invert the hierarchy. Put the null node at the base:
class Node {
public:
Node() {}
virtual void visit() const {}
};
Then specialize as needed:
template<typename T>
class DataNode : public Node {
public:
DataNode(T x, const Node* l=&Null, const Node* r=&Null)
: left(l), right(r), data(x) {}
virtual void visit() const {
left->visit();
std::cout << data << std::endl;
right->visit();
}
private:
const Node *left, *right;
T data;
static const Node Null;
};
template<typename T>
const Node DataNode<T>::Null = Node();
Sample usage:
int main()
{
DataNode<char> a('A', new DataNode<char>('B'),
new DataNode<char>('C'));
a.visit();
return 0;
}
Output:
$ ./node
B
A
C