I have a class ID3 and a class Tree. An object of Class Tree is used in ID3 and its showing an error that Tree is not declared.
Code looks like
#include <iostream>
#include <algorithm>
#include <cstdlib>
#include <math.h>
#include <vector>
using namespace std;
class ID3 {
public:
string v[];
int x;
public:
double Hi(Tree data)
{
int y=x-1;
}
};
class Tree{
Tree();
}
You need to forward declare Tree before using it in ID3, otherwise the compiler doesn't know what Tree is:
class Tree;
class ID3 {
...
If you need to use an instance of Tree somewhere then you need to have the full definition of Tree before that point, for example:
class Tree {
Tree();
};
class ID3 {
...
double Hi(Tree data) {
// do something with 'data'
int y=x-1;
}
};
For more information about when to use forward declarations, see this Q&A.
In general, C++ is compiled from top to bottom. So if the class ID3 needs the class Tree, Tree must be defined before ID3. Just put the class Tree before ID3 and it should be fine.
Forward deceleration of Tree will do the job. At the point where you used Tree instance in ID3, the compiler knows nothing about your Tree class, compiling process goes from up to bottom.
Related
following situation:
I have in one dll a template class Point
namespace Image
{
template<typename T> class Point
{
.
.
.
and tring to use this class in another dll. The class looks like:
//Base.h
template<typename T> class Point;
class Base{
Point<double> _Point;
};
//Child.h
#include "Base.h"
class Child : public Base{
Child(Point<double> pt);
doSth();
}
//Child.cpp
#include "Child.h"
#include "Point.h"
Child::Child(Point<double> pt){
_Point = pt;
}
Child::dosth(){
Point<double> p = _Point; // In this Row i get an "undefined type 'Point<double>' Error
}
Any ideas why i get the error?
is my idea totally wrong to forward declare the Point-Class in the header file and make the include in the .cpp ?
Thank you very much, have a nice day!
With the forward declaration you have in Base.h it doesn't matter if you used using namespace Image; first, the template class you declare in Base.h is still in the global namespace and not in the Image namespace. And that declaration will take precedence over the one in the Image namespace.
So there are really two solutions here: Either explicitly use Image::Point, or remove the forward declaration in Base.h (and include the header file where Image::Point<> is defined).
I am trying to create a binary search tree of Player objects. I have previously defined the Player class. However, when I go to include the player object in the structure for each node of the BST, I get an error that Player is undefined even though I thought I had set up the includes properly.Is there any way for me to go about this without having to rethink my implementation?
I simplified the code a little to demonstrate:
BST header:
class Player;
class BinarySearchTree{
private:
struct Node {
Player info;
Node* left;
Node* right;
};
Node *root;
void Insert(Node*& tree, Player p);
void PrintTree(Node* tree, std::ostream& out);
};
BST.cpp
#include "Player.h"
#include "BinarySearchTree.h"
//all methods implemented afterwards
Player.h
class Player{
private:
std::string* name = new std::string;
int* score = new int;
public:
//....
};
Player.cpp
#include "Player.h"
//...
Compiler needs to see the definition of class Player in header file (BST.h) which you have provided in BST.cpp ( by including "Player.h").
So, BST header should be:-
#include "Player.h" <<<include this file
class Player; <<<remove this forward declaration
class BinarySearchTree
{
private:
struct Node {
Player info;
So to toy with friend functions, I decided to make a Child class and a Mother class. The Mother class has a data member that is a Child. The Child class makes two methods of the Mother class friend functions.
When I compile though, it seems that no matter how I handle inclusions I end up with an error. If the Child is the first one to get defined, I get "Mother is not a class or namespace name" for the line friend void Mother::setChildName(string name); in Child.h. If the Mother is the first one to get defined, I get "Missing type specifier" for the line Child c; in Mother.h.
Is there a way around this? I tried putting class Mother; at the top of the Child.h and class Child; at the top of Mother.h and that didn't seem to help.
Or is this kind of circular reference just always going to fail?
In Mother.h:
#ifndef MOTHER_H_
#define MOTHER_H_
#include <string>
#include "Child.h"
using namespace std;
class Mother {
public:
Mother();
void setChildName(string name);
string getChildName();
private:
Child c;
};
#endif
In Mother.cpp:
#include <string>
#include "Mother.h"
using namespace std;
void Mother::setChildName(string name) {
c.name = name;
}
string Mother::getChildName() {
return c.name;
}
In Child.h:
#ifndef CHILD_H_
#define CHILD_H_
#include <string>
#include "Mother.h"
using namespace std;
class Child {
public:
private:
string name;
friend void Mother::setChildName(string name);
friend string Mother::getChildName();
};
#endif
This particular problem cannot be solved without redesign. Mother needs to be defined before Child, and Child needs to be defined before Mother. The simple way is to make the whole Mother class a friend of Child. That way Child can be defined first.
I think there little practical benefit in making individual methods friends of another class. That would imply that your class is so big that it's responsibilities could be divided into smaller classes.
if Mother will hold pointer to child, you will not have to include child.h. forward deceleration will be enough.
Hi am having problems compiling some code, I have a situation where A depends and B depends on A. I have put forward declarations but I keep getting the problems.
In file included from src/MemoWriteContext.h:7:0,
from src/MemoWriteContext.cpp:1:
src/MemoContext.h:29:20: error: field ‘memoWriteContext’ has incomplete type
MemoContext.h
#ifndef MEMOCONTEXT_H_
#define MEMOCONTEXT_H_
#include "sqlite/SqliteDb.h"
#include "Context.h"
#include "MemoWriteContext.h"
#include <string>
#include <memory>
#include <map>
namespace bbs
{
class MemoWriteContext;
class MemoContext : public Context
{
public:
//'structors
MemoContext(const std::map<std::string, std::shared_ptr<Context> > &_contexts,
sqlitecpp::SqliteDb &_sqliteDb);
~MemoContext();
protected:
//when called write the data back to the user
void performAction(const std::string &data, std::shared_ptr<UserAgent> agent);
private:
MemoWriteContext memoWriteContext;
}; //class memocontext
}
#endif // MEMOCONTEXT_H_
MemoWriteContext.h
#ifndef MEMOWRITECONTEXT_H_
#define MEMOWRITECONTEXT_H_
#include "Context.h"
#include "sqlite/SqliteDb.h"
#include "sqlite/PreparedStmt.h"
#include "MemoContext.h"
#include <string>
#include <memory>
#include <map>
namespace bbs
{
class MemoContext; //forward decl
class MemoWriteContext : public Context
{
public:
//'structors
MemoWriteContext(const std::map<std::string, std::shared_ptr<Context> > &_contexts,
MemoContext &_memoContext, sqlitecpp::SqliteDb &_sqliteDb);
~MemoWriteContext();
protected:
//when called write the data back to the user
virtual void performAction(const std::string &data, std::shared_ptr<UserAgent> agent);
virtual void onReceiveUserAgent(std::shared_ptr<UserAgent> agent);
private:
MemoContext &memoContext; //parent;
sqlitecpp::SqliteDb &sqliteDb;
sqlitecpp::PreparedStmt writeMemoStmt;
sqlitecpp::PreparedStmt findAgentIdStmt;
};
enum class MemoWriteState : char
{
USERNAME=0,
MESSAGE,
CONFIRM
};
class MemoWriteAgentData : public ContextAgentData
{
public:
MemoWriteState state;
int userId;
std::string message;
}; //class Memo Write Agent data
}
#endif // MEMOWRITECONTEXT_H_
Full source here.
I think your only problem is that MemoWriteContext.h has #include "MemoContext.h". The context only requires a reference which can use the forward declaration. But if you happen to include MemoWriteContext.h first it will then bring in MemoContext.h before it actually declares class MemoWriteContext. That will then use the forward declaration of class MemoWriteContext and fail. You can even see the ordering in your error message.
Just remove that #include or at least reverse the order of the includes in MemoWriteContext.cpp (since each .h including the other effectively reverses them back).
This:
class MemoWriteContext;
Is a forward declaration. It's an "incomplete type", and therefore cannot be instantiated.
The reason is that a C++ compiler must know the size of any type that has to be instantiated. Incomplete types have no size.
By the way, you can do this:
MemoWriteContext * ptr;
Because you actually declare a pointer, and pointers have a known size.
If you want to avoid dynamic allocations, then you'll have to fully declare the type by including MemoWriteContext.h and removing the forward declaration.
I'm experiencing some problems with breaking my code to reusable parts using templates and inheritance. I'd like to achieve that my tree class and avltree class use the same node class and that avltree class inherits some methods from the tree class and adds some specific ones. So I came up with the code below. Compiler throws an error in tree.h as marked below and I don't really know how to overcome this. Any help appreciated! :)
node.h:
#ifndef NODE_H
#define NODE_H
#include "tree.h"
template <class T>
class node
{
T data;
...
node()
...
friend class tree<T>;
};
#endif
tree.h
#ifndef DREVO_H
#define DREVO_H
#include "node.h"
template <class T>
class tree
{
public: //signatures
tree();
...
void insert(const T&);
private:
node<T> *root; //missing type specifier - int assumed. Note: C++ does not support default-int
};
//implementations
#endif
avl.h
#ifndef AVL_H
#define AVL_H
#include "tree.h"
#include "node.h"
template <class T>
class avl: public tree<T>
{
public: //specific
int findMin() const;
...
protected:
void rotateLeft(node<T> *)const;
private:
node<T> *root;
};
#endif
avl.cpp (I tried separating headers from implementation, it worked before I started to combine avl code with tree code)
#include "drevo"
#include "avl.h"
#include "vozlisce.h"
template class avl<int>; //I know that only avl with int can be used like this, but currently this is doesn't matter :)
//implementations
...
Both tree.h and node.h try to include each other, the include guards will prevent one of them from seeing the other.
Instead of #include "tree.h" try forward declaring tree like:
template <class T>
class tree;
in node.h
EDIT: As sbi suggested in a comment, it makes more sense to forward declare tree in node.h than the other way around, since it's about granting tree access to node through a friend declaration.
Don't #include "tree.h" in "node.h".
Also, you've declared root in both the tree and avl classes. Qualify tree::root as protected and remove avl::root.
Your problem is that tree.h includes node.h and vice versa. I would not have thought it is necessary (or makes much sense) for the node to have to know about the tree or to grant it friendship, so I'd remove that.
The problem is because of the circular dependency of header files between tree.h and node.h . Since node.h includes tree.h, while compiling the tree class, compiler doesn't know what is the type of node. Since you are using it just for declaring a friend there is no need to include the header file tree.h in node.h