I'm trying to implement a tree-like structure with two classes: Tree and Node. The problem is that from each class I want to call a function of the other class, so simple forward declarations are not enough.
Let's see an example:
Tree.h:
#ifndef TREE_20100118
#define TREE_20100118
#include <vector>
#include "Node.h"
class Tree
{
int counter_;
std::vector<Node> nodes_;
public:
Tree() : counter_(0) {}
void start() {
for (int i=0; i<3; ++i) {
Node node(this, i);
this->nodes_.push_back(node);
}
nodes_[0].hi(); // calling a function of Node
}
void incCnt() {
++counter_;
}
void decCnt() {
--counter_;
}
};
#endif /* TREE_20100118 */
Node.h:
#ifndef NODE_20100118
#define NODE_20100118
#include <iostream>
//#include "Tree.h"
class Tree; // compile error without this
class Node
{
Tree * tree_;
int id_;
public:
Node(Tree * tree, int id) : tree_(tree), id_(id)
{
// tree_->incCnt(); // trying to call a function of Tree
}
~Node() {
// tree_->decCnt(); // problem here and in the constructor
}
void hi() {
std::cout << "hi (" << id_ << ")" << endl;
}
};
#endif /* NODE_20100118 */
Calling Tree:
#include "Tree.h"
...
Tree t;
t.start();
This is just a simple example to illustrate the problem. So what I want is calling a function of Tree from a Node object.
Update #1: Thanks for the answers. I tried to solve the problem like in Java, i.e. using just one file per class. It seems I will have to start separating .cpp and .h files...
Update #2: Below, following the hints, I pasted the complete solution too. Thanks, problem solved.
In the headers, forward declare the member functions:
class Node
{
Tree * tree_;
int id_;
public:
Node(Tree * tree, int id);
~Node();
void hi();
};
In a separate .cpp file that includes all the required headers, define them:
#include "Tree.h"
#include "Node.h"
Node::Node(Tree * tree, int id) : tree_(tree), id_(id)
{
tree_->incCnt();
}
Node::~Node()
{
tree_->decCnt();
}
etc
This also has the effect of keeping your headers readable, so it is easy to see a class's interface at a glance.
Following the hints, here is the complete solution.
Tree.h:
#ifndef TREE_20100118
#define TREE_20100118
#include "Node.h"
#include <vector>
class Tree
{
int counter_;
std::vector<Node> nodes_;
public:
Tree();
void start();
void incCnt();
void decCnt();
};
#endif /* TREE_20100118 */
Tree.cpp:
#include "Tree.h"
#include "Node.h"
Tree::Tree() : counter_(0) {}
void Tree::start()
{
for (int i=0; i<3; ++i) {
Node node(this, i);
this->nodes_.push_back(node);
}
nodes_[0].hi(); // calling a function of Node
}
void Tree::incCnt() {
++counter_;
}
void Tree::decCnt() {
--counter_;
}
Node.h:
#ifndef NODE_20100118
#define NODE_20100118
class Tree;
class Node
{
Tree * tree_;
int id_;
public:
Node(Tree * tree, int id);
~Node();
void hi();
};
#endif /* NODE_20100118 */
Node.cpp:
#include "Node.h"
#include "Tree.h"
#include <iostream>
Node::Node(Tree * tree, int id) : tree_(tree), id_(id)
{
tree_->incCnt(); // calling a function of Tree
}
Node::~Node() {
tree_->decCnt();
}
void Node::hi() {
std::cout << "hi (" << id_ << ")" << std::endl;
}
The definition of Tree requires the definition of Node but not the other way around so your forward declaration is correct.
All that you have to do is removed the definition of any functions that require a full definition of Tree from the Node class body and implement them in a .cpp file where full definitions of both classes are in scope.
Can you but the constructor/destructor bodies in a .cxx file? You could include Tree.h there.
Related
I am implementing bptree using c++. I am am stuck in the initial step of node creation. Keep getting "C2011 'Node':'class' type redefinition" error. I found some suggestions online to remove class key word from cpp file. But when I remove class keyword I get lots of other errors. here is my code for Node.cpp:
#include "Node.h"
#include <cstdio>
#include <iostream>
#include <string>
#include <map>
using namespace std;
class Node {
bool leaf;
Node** kids;
map<int, string> value;
int keyCount;//number of current keys in the node
//constructor;
Node::Node(int order) {
this->value = {};
this->kids = new Node *[order + 1];
this->leaf = true;
this->keyCount = 0;
for (int i = 0; i < (order + 1); i++) {
this->kids[i] = NULL;
}
}
};
and Node.h file is as following:
#pragma once
#ifndef NODE_HEADER
#define NODE_HEADER
class Node {
public:
Node(int order) {};
};
#endif
How can I fix this?
Problem
In C++, headers are simply pasted into the body when you #include. So now the compiler sees:
class Node {
public:
Node(int order) {};
};
// stuff from system headers omitted for brevity
using namespace std;
class Node {
bool leaf;
//...
};
There are two problems here:
compiler sees class Node twice with different bodies.
Node::Node is defined twice (first time empty {}).
Solution
The header should include class declaration:
#include <map>
using namespace std;
class Node {
bool leaf;
Node** kids;
map<int, string> value;
int keyCount;//number of current keys in the node
//constructor;
Node(int order);
};
Note that the constructor has no body here. It's just a declaration. Because it uses map you need to include <map> and add using namespace before the declaration.
After that don't put class Node again in the .cpp or .cc file. Only put the method implementations at the top level:
Node::Node(int order) {
// ...
}
I am getting the following error:
'class name' does not name a type for all of my classes.
I suspect it may be a circular dependency but I have no clue how to solve it as each class requires access to a function from the next. Below are my classes:
Container.h:
#ifndef CONTAINER_H
#define CONTAINER_H
#include "Factory.h"
class Container
{
public:
Container()
{
array = new int[10];
for (int i = 0; i < 10; ++i) {
array[i] = i;
}
}
Iterator* createIterator()
{
Factory fac;
return fac.factoryMethod();
}
friend class Iterator;
private:
int* array;
};
#endif //CONTAINER_H
Factory.h:
#ifndef FACTORY_H
#define FACTORY_H
#include "Iterator.h";
class Factory
{
Iterator* factoryMethod(Container* con)
{
return new Iterator(con);
}
};
#endif //FACTORY_H
Iterator.h:
#ifndef ITERATOR_H
#define ITERATOR_H
#include "Container.h"
class Iterator
{
public:
Iterator(Container* con)
{
this->con =con;
}
int getFromIndex(int i)
{
return con->array[i];
}
private:
Container* con;
};
#endif //ITERATOR_H
main.cpp:
#include <iostream>
using namespace std;
#include "Container.h"
#include "Iterator.h"
int main() {
Container con;
Iterator* it = con.createIterator();
cout<<it->getFromIndex(2)<<endl;
return 0;
}
Thank you in advance for any help.
It is indeed a circular dependency between your headers. Container.h includes Factory.h, which includes Iterator.h, which includes Container.h.
The solution is to move the implementations of member functions from header files into source files. That way, header files will only need declarations, not definitions, of the classes, which you can easily put directly in the "consuming" header files:
class Iterator;
class Container
{
public:
Container();
Iterator* createIterator();
friend class Iterator;
private:
int* array;
};
Then, in an appropriate source file (such as Container.cpp), implement the member functions and include any headers you need:
Container.cpp
#include "Container.h"
#include "Factory.h"
Container::Container() : array(new int[10])
{
for (int i = 0; i < 10; ++i) {
array[i] = i;
}
}
Iterator* Container::createIterator()
{
Factory fac;
return fac.factoryMethod();
}
(Dtto for Factory and Iterator, of course).
Don't forget to link all the source files together when building your final binary.
I had defined a class "Progression" and saved it as "Progression.h" and then i made another class "ArithProgression" which extends Progression class and saved it as "ArithProgression.h".
File: Progression.h
#ifndef PROGRESSION_H
#define PROGRESSION_H
#include <iostream>
using namespace std;
class Progression
{
public:
Progression()
{
cur=first=0;
}
Progression(long f)
{
cur=first = f;
}
void printProgression(int n)
{
cout<<firstValue();
for(int i=0;i<=n; i++)
{
cout<<' '<<nextValue();
}
}
virtual ~Progression() {}
protected:
long first;
long cur;
virtual long firstValue()
{
cur= first;
return cur;
}
virtual long nextValue()
{
return cur++;
}
};
#endif // PROGRESSION_H
FILE: ArithProgression.h
#ifndef ARITHPROGRESSION _H
#define ARITHPROGRESSION _H
#include "Progression.h"
class ArithProgression :public Progression
{
public:
ArithProgression(long i=1)
:Progression()
{
inc=i;
}
virtual ~ArithProgression () {}
protected:
long inc;
virtual long nextValue()
{
cur+=inc;
return cur;
}
private:
};
#endif // ARITHPROGRESSION _H
FILE: main.cpp
#include <iostream>
#include "Progression.h"
#include "ArithProgression.h"
using namespace std;
int main()
{
Progression* p;
p= new ArithProgression();
p->printProgression(10);
delete p;
}
I am getting an error: "cannot convert 'ArithProgression*' to 'Progression*' in assignment" in code blocks 12.11
Please Help
Your code, as you posted it, works just fine. Since ArithProgression is indeed a subclass of Progression, the above code cannot trigger that error.
I have created a link list program that performs several functions. I've written a function to destroy the list that takes "top" as a parameter. I eventually use this function in my destructor. Can I actually test this?
Here is my shortened Family.h:
#ifndef FAMILY_H
#define FAMILY_H
#include<string>
using namespace std;
#include "Child.h"
#include "Wife.h"
#include "Husband.h"
class Family
{
protected:
HusPtr top;
void Destroy(HusPtr& top); //I know in order to access this in the Main, I'd have to make
//this Public. But I'd have to create a local pointer named top.
//Because the local pointer points to nothing, I get a segmentation
//fault.
public:
Family();
Family(HusPtr& h);
Family(const Family& source);
~Family();
};
#endif
Here is my Destroy function in my Family.cpp:
void Family::Destroy(HusPtr& top)
{
HusPtr curr = top;
WifePtr w = curr->myWife;
while(curr != NULL)
{
if(curr->myWife != NULL)
{
while(w->myChildren != NULL)
{
ChildPtr c = w->myChildren;
ChildPtr cNext = c->mySibling;
w->myChildren = cNext;
delete c;
}
curr->myWife = NULL;
delete w;
}
HusPtr next = curr;
curr = next->nextFamily;
delete next;
top = curr;
}
}
My Main.cpp:
using namespace std;
#include "Family.h"
HusPtr top; //points to nothing.
int main()
{
Family F1;
F1.ProcessTransaction("transaction.txt");
F1.Destroy(top);// gives a segmentation fault...likely due to the fact that top points to nothing.
}
Wife.h:
#ifndef HUSBAND_H
#define HUSBAND_H
#include<string>
using namespace std;
#include "Person.h"
class Husband;
typedef Husband* HusPtr;
class Wife;
typedef Wife* WifePtr;
class Husband:public Person
{
friend class Wife;
friend class Family;
protected:
HusPtr nextFamily;
WifePtr myWife;
public:
Husband();
Husband(long hSSN, string hFirst, string hLast);
void Print() const;
};
#endif
Wife.h:
#ifndef WIFE_H
#define WIFE_H
#include<string>
using namespace std;
#include "Person.h"
#include "Child.h"
class Child;
typedef Child* ChildPtr;
class Wife:public Person
{
friend class Family;
protected:
ChildPtr myChildren;
public:
Wife();
Wife(long wSSN, string wFirst, string wLast);
void Print() const;
};
#endif
Child.h:
#ifndef CHILD_H
#define CHILD_H
#include<string>
using namespace std;
#include "Person.h"
class Child;
typedef Child* ChildPtr;
class Child:public Person
{
friend class Family;
protected:
ChildPtr mySibling;
public:
Child();
Child(long cSSN, string cFirst, string cLast);
void Print() const;
};
#endif
This is not a needed function in this assignment, but I decided to implement it anyway. Everything maps out fine and should work, but I really think that the segmentation fault I receive is due to the fact that I'm passing a pointer created in Main.cpp that isn't pointing anywhere. Am I correct?
In second iteration after deleting w, you are not assigning it again. But you try to access its children again. so it get crashed.
in while loop
first iteration
...
delete w;
second iteration
w->children; program will be crashed.
#ifndef SLIST_H
#define SLIST_H
#include "llist.h"
using namespace std;
class slist:public llist{
public:
slist();
int search(el_t Key);
void replace(el_t Elem, int I);
};
#endif
That is my new class I just made that gives me the search and replace function, on top of all the inherited functions contained in llist.h
In my main...
#include "slist.h"
#include <iostream>
using namespace std;
int main(){
slist list;
list.addFront(4);
cout<<list.search(4);
}
I'm trying to call addfront() which is a public function in the llist class. Then I want to call search() which is an inherited public function of the slist class. g++ gives me a few errors that I don't understand.
slist.h: In function âint main()â:
slist.h:10: error: âslist::slist()â is protected
main.cpp:7: error: within this context
slist() is protected? Why's that? I put it under public:
Also whats up with the this context, I'm guessing I'm just doing the whole inheritance thing totally wrong. Any help would be appreciated!
Edit: Here's the llist class, if it helps
#ifndef LIST_H
#define LIST_H
#include <iostream>
using namespace std;
class llist{
protected:
typedef int el_t;
el_t total;
struct Node{
int Elem;
Node *Next;
};
Node *Front;
Node *Rear;
Node * Curr;
public:
class Overflow{};
class Underflow{};
class Range{};
llist();
~llist();
bool isEmpty();
void displayAll();
void addRear(el_t NewNum);
void deleteFront(el_t& OldNum);
void addFront(el_t NewNum);
void deleteRear(el_t& OldNum);
void deleteIth(int I, el_t& OldNum);
void addbeforeIth(int I, el_t newNum);
class Overflow;
};
#endif
This is llist.cpp with only the relevant functions pasted
#include "llist.h"
#include <iostream>
using namespace std;
int total=0;
llist::llist(){
Front=NULL;
Rear=NULL;
total=0;
}
llist::~llist(){
while(Front!=NULL){
int z;
deleteFront(z);
}
}
bool llist::isEmpty(){
if(Front==NULL){
return true;
}
return false;
}
void llist::displayAll(){
Curr=Front;
if(isEmpty()){
cout<<"[ empty ]"<<endl;
}else{
while(Curr!=NULL){\
cout<<"curr != NuL"<<endl;
cout<<Curr->Elem<<endl;
Curr=Curr->Next;
}
}
}
void llist::addFront(el_t NewNum){
if(isEmpty()){
Node *x=new Node;
x->Next=Front;
Rear=Front;
Front=x;
Front->Elem=NewNum;
}else{
Node *x=new Node;
x->Next=Front;
Front=x;
Front->Elem=NewNum;
++total;
}
}
I honestly can't see the problem but not every compiler is standard-compliant, so I would try the following:
1) Rename your class - if it works, that means it's a because of a naming conflict.
2) Remove the using directives.
3) Remove the inheritance. If it works after this... you really need to change compilers.
4) Try #undef public before your class declaration. If it works after this... well, someone's in for a talk with the manager.
5) Pray...