Problem about Initializing inner class Instance - c++

class ListNode;
class LinkedList {
private:
ListNode* start;
class ListNode {
private:
int data;
ListNode* next;
public:
ListNode() : data(-1), next(NULL) {}
ListNode(int data, ListNode* next=NULL) : data(data), next(next) {}
};
public:
LinkedList() : start(NULL) {}
LinkedList(int data) : start(new ListNode(data)) {}
};
there is a error in LinkedList(int data) : start(new ListNode(data)) {}.
It says "you cannot innitialize LinkedList* value using LinkedList::ListNode construction".
Whats is the exact problem means and solutions???

The forward declaration of class ListNode; is not the same thing as class LinkedList::ListNode defined later.
When the compiler finds ListNode* start;, LinkedList::ListNode is unknown, so the compiler uses the ListNode forward declaration. By the time the compiler gets to start(new ListNode(data)), LinkedList::ListNode is known and has a closer scope so it is used instead of ListNode.
Result: start, a ListNode * is pointed at a LinkedList::ListNode. The types clash and the compiler rejects the code.
The simplest solution is to remove the forward declaration of ListNode, since it's likely just an attempt a to fix an earlier undeclared identifier error and will never be defined, and move ListNode* start; to after the definition of LinkedList::ListNode so that there is no ambiguity.

You cannot forward declare an inner class outside the containing class. So, try declaring it first, and then declaring a pointer to it:
class LinkedList {
private:
class ListNode {
private:
int data;
ListNode* next;
public:
ListNode() : data(-1), next(NULL) {}
ListNode(int data, ListNode* next=NULL) : data(data), next(next) {}
};
ListNode* start;
public:
LinkedList() : start(NULL) {}
LinkedList(int data) : start(new ListNode(data)) {}
};

Related

can i restrict behaviour of polymorphism?

So i'm trying to implement a binary search tree and avl tree. Each of these classes using different but similar types of nodes. The classes for nodes look like this:
class node
{
protected:
int key;
node* parent, * left, * right;
public:
node(int key, node* parent = nullptr) :key(key), parent(parent), left(nullptr), right(nullptr) {}
~node() {}
};
class avl_node : public node
{
private:
int height;
public:
avl_node(int key, int height, avl_node* parent = nullptr) :node(key, parent), height(height) {}
~avl_node() {}
};
This mostly works. Any node can have connexions with any other node, and any avl_node with any other avl_node. The issue that I think of is that a node could technically have a parent or children avl_node because of polymorphism, and I wouldn't want that to happen. Although I can avoid that by being careful, i wouldn't want it to be possible at all. Is there a way?
p.s. I want to keep the classes related
If it's enough, you could explicitly delete the version of constructor that would take an avl_node*
class node
{
protected:
int key;
node* parent, * left, * right;
public:
node(int key, node* parent = nullptr) :key(key), parent(parent), left(nullptr), right(nullptr) {}
node(int, avl_node*) = delete;
~node() {}
};
Of course, this solution is not foolproof. If you brought an avl_node hidden behind a node pointer, the compiler wouldn't be able to tell (and since polymorphism is mainly dynamic, you would only be protected in this specific case where you attempt to assign the pointer directly)
This would compile.
avl_node myavl;
node n(0, static_cast<node*>(&myavl));
You could try dynamic-casting in the node constructor to tell if it's an avl_node being passed (your nodes would need a vtable for that), but that would make it impossible to call the constructor like that from the avl_node constructor.
Another option would be making a separate constructor intended specifically for the subclass
class node
{
protected:
int key;
node* parent, * left, * right;
node(int key, avl_node* parent) : key(key), parent(parent), left(nullptr), right(nullptr) {}
public:
node(int key, node* parent = nullptr) :key(key), parent(parent), left(nullptr), right(nullptr) { /* do something to not allow avl_node* to be passed */ }
~node() {}
};
You can get rid of polymorphism and avoid code duplication by using a class template for the base, and members that depend on the template argument.
Example:
template<typename T>
class node
{
protected:
int key;
node* parent, * left, * right; // Note: these are actually 'node<T>'.
public:
node(int key, node* parent = nullptr)
: key(key), parent(parent), left(nullptr), right(nullptr) {}
void set_parent(node* p) { parent = p; }
};
class avl_node : public node<avl_node>
{
private:
int height;
public:
avl_node(int key, int height, avl_node* parent = nullptr)
: node(key, parent), height(height) {}
};
class silly_node : public node<silly_node>
{
public:
silly_node() : node(0) {}
};
int main()
{
// Fine
avl_node an(0, 1);
// Fine
avl_node bn(0, 1, &an);
// Also fine
bn.set_parent(&an);
// Fine
silly_node sn;
// Compilation error
avl_node cn(0, 1, &sn);
// Also compilation error
bn.set_parent(&sn);
}

how to write constructor prototype for a struct in a class

I created a class BST and I am facing problem in creating constructor of a struct node in it.
class BST{
private:
struct node{
int key;
node* left;
node* right;
};
node* root;
public:
//constructor for BST
BST();
//constructor for node
node(int x);
};
I get an error expected unqualified-id before 'int'.
So,I read what is an unqualified-id but didn't understand why is it needed here.
Constructors for classes and structs must be declared within the definition of the class/struct. Your version does not do this, as node(int) is declared outside the node class.
Change your code to this:
class BST
{
private:
struct node
{
int key;
node* left;
node* right;
node(int x);
};
node* root;
public:
BST();
};
Then if you decide to implement the node constructor outside of the BST class:
BST::node::node(int x)
{
// code here
}

Redefinition as different kind of symbol using friend class C++14

I am trying to write a template for a class. This class uses a Node class within it so I have defined the Node class as having the List class as a friend. See below.
template <typename T>
class Node {
private:
Node() {
next = nullptr;
prev = nullptr;
}
Node(int data) : Node() { this->data = data; }
Node *next;
Node *prev;
int data;
friend class DoubleLinkedList;
};
template<typename T>
class DoubleLinkedList {
public:
DoubleLinkedList();
~DoubleLinkedList();
private:
Node *_head;
Node *_tail;
};
I have another file where the classes are implemented. I get this error with or without the template definition above the List class. Can someone explain this?
This works for me:
template <typename T>
class Node
{
private:
Node()
{
next = nullptr;
prev = nullptr;
}
Node(int data) : Node() { this->data = data; }
Node *next;
Node *prev;
int data;
template<typename T> friend class DoubleLinkedList;
};
template<typename T>
class DoubleLinkedList
{
public:
DoubleLinkedList();
~DoubleLinkedList();
private:
Node<T> *_head;
Node<T> *_tail;
};

proxy class constructor access

I have some troubles with a c++ project i started. I am trying to implement basic linked list and my attempt includes proxy class in the list class for representing single node. One of the list constructors can get single parameter and initialize the first node of the list with it, but i can't pass that parameter to the proxy class' constructor. Any suggestions how to do it?
Here is some c++ code
template <class TYPE>
class list{
private:
//Proxy class for node representation
class node{
private:
node* next;
TYPE data;
public:
explicit node() : next(nullptr) {}
node (const TYPE& init) : data(init) {}
inline node*& get_next(){
return next;
}
inline TYPE& get_data(){
return data;
}
};
node* head;
unsigned int size;
public:
explicit list() : head(nullptr), size(0) {}
list(const TYPE& init) : list::node(init) {}
Well, you should refer to the instance of node rather than to the class itself. Also, keep in mind that head is a pointer in your example.
Try something like this:
list(const TYPE &init) : head(new node(init)) {}

Classes & Structs, no default contructor

I'm trying to build a Linked List who's elements are of my own specified type. Now I'm not going to lie I'm winging a lot of this having not had much experience with OOP in C++ but I'm stuck with a single error.
My LinkedList:
#include "Vehicle.h"
#include "string"
using namespace std;
class LinkedList
{
private:
struct Node
{
Vehicle data;
Node* next;
};
Node* root;
int noofitems;
public:
LinkedList();
int getNoOfItems();
Vehicle getItemByIndex(int index);
void addItem(Vehicle itemIn);
void deleteItem();
void insertItem(Vehicle itemIn);
~LinkedList();
};
The Constructor and addItem()
LinkedList::LinkedList() : root(NULL), noofitems(0) {}
void LinkedList::addItem(Vehicle itemIn)
{
Node* temp;
temp = new Node();
temp->data = itemIn;
temp->next = this->root;
this->root = temp;
}
My compiler is giving me this error:
error C2512: 'LinkedList::Node' : no appropriate default constructor available. Now I've tried giving the struct a constructor like so:
struct Node
{
Vehicle data;
Node* next;
Node() : next(NULL) {}
};
But then I get a new error on top of the old one: IntelliSense: no default constructor exists for class "Vehicle". The word constructor is starting to look wrong and I'm really frustrated. Thanks In advance.
By the way if details of the vehicle class are needed:
class Vehicle
{
protected:
string make;
string model;
string regNo;
int engineSize;
bool rented;
public:
Vehicle(string makeIn, string modelIn, string regNoIn, int engineSizeIn);
string getMakeModel(); // return two values concatinated
string getRegNo();
int getEngineSize();
bool getRented();
void setRented(bool rentedIn);
~Vehicle();
};
Vehicle::Vehicle(string makeIn, string modelIn, string regNoIn, int engineSizeIn) :
make(makeIn), model(modelIn), regNo(regNoIn), engineSize(engineSizeIn),
rented(false)
{}
string Vehicle::getMakeModel()
{
return make + " " + model;
}
string Vehicle::getRegNo()
{
return regNo;
}
int Vehicle::getEngineSize()
{
return engineSize;
}
bool Vehicle::getRented()
{
return rented;
}
void Vehicle::setRented(bool rentedIn)
{
rented = rentedIn;
}
Vehicle::~Vehicle(){}
Node has a member of type Vehicle. Since you cannot default construct a Vehicle the default constructor for Node is marked as deleted. You will need to provide your own default constructor that constructs the Vehicle member to some state like
struct Node
{
Vehicle data;
Node* next;
Node() : data("", "", "", 0), next(nullptr) {}
};
or provide a default constructor for Vehicle like
class Vehicle
{
//...
public:
Vehicle() = default;
//...
};
The error is self explanatory. You have not explicitly initialized vehicle in your Node class as shown:
struct Node
{
Vehicle data;
Node* next;
Node() : next(NULL) {} // NO initialization for vehicle
};
The compiler will try and then construct a Vehicle using it's default constructor, but it finds none. In your vehicle class you have defined a constructor taking arguments:
Vehicle(string makeIn, string modelIn, string regNoIn, int engineSizeIn);
Thus the compiler will not generate one for you. To fix this you can either define a default constructor yourself, or you can declare one with the word default which will force the compiler too generate one: