I have multiple C++ classes in a Pacman Game project (Maze, Food, Pacman, ...). I made a namespace 'Pacman_AI' so that the classes can be seen every where in the project. However, I got an error for 'GameObject' class: "name followed by '::' must be a class or namespace name".
Here is my "GameObject.cpp" in which I get the error above:
namespace Pacman_AI{
vector <pair <int, int> > GameObject::getPoints(){
return points;
}
string GameObject::getType(){
return type;
}
}
I already defined my "GameObject" class in a different file "GameObject.h".
Your help is highly appreciated.
The simplest thing is to use namespace in your header files
// Foo.h
namespace Pacman_AI{
// STUFF HERE
};
and then using namespace in your .cpp files
//Foo.cpp
#include "Foo.h"
using namespace Pacman_AI;
// define your functions here
Related
I got this C++ code:
Client.h:
#include <unordered_map>
using namespace std;
class Client{
static unordered_map<int, Client*>* clients;
public:
static void initializeClients();
}
Client.cpp
#include "Client.h"
#include <unordered_map>
using namespace std;
void Client::initializeClients(){
clients = new unordered_map<int, Client*>();
}
But the linker gives me a LNK2001 unresolved external symbol for the unordered_map. I have no idea of what I am doing wrong, but it seems that I am missing something. I am using Visual Studio 2013.
Any idea? Thank you in advice!
you need to declare clients in your cpp file :
#include "Client.h"
#include <unordered_map>
using namespace std;
unordered_map* Client::clients;
void Client::initializeClients(){
clients = new unordered_map<int, Client*>();
}
explenation:
header file only tells the linker what kinds of symbols some cpp file(s) has. declaring a variable in the header file does not makes this variable appear by it self. here you need to instantiate the static map pointer in the cpp file by declaring it , and make other files know about him by specifing it in the header file
summery :
static member variables and global variables need to be declared also in some cpp file in order to get instantiated
To keep class definition in header file clean, I decided to move implementations of templated functions into another *.h file, which I include in the main header. Now I would like to make use of using namespace there, to make code more readable.
But using namespaces would affect the whole application, since the file gets included in the header which itself gets included in the whole application. The using of the namespaces would spread out of the file.
How can I handle this?
You can put using namespace XX inside function definitions to scope the using declaration to that function:
int func( ...args... )
{
using namespace std;
// ... body of function
}
Use a namespace alias.
namespace submod_ = topspace::other_project::module::submodule;
Then you can use submod_ wherever you would require the very long namespace.
This requires you to still use submod_ where you would have the long namespace qualifier. In that sense, it doesn't exactly answer your question. But I would argue that the explicitness of the qualification aids readability and helps prevent mistakes.
There are real examples of StackOverflow questions where a "using" declaration brought in "lurking" functions which the code author did not realize.
You can place the using namespace in the namespace of your 'main header':
Header.h
#include <string>
namespace Test
{
using namespace std;
string f()
{
return "Test";
};
}
main.cpp
#include "Header.h"
int main()
{
Test::f();
string test; // Error: identifier "string" is undefined
std::string test;
return 0;
}
I want to use the forward declaration for the ptree class of boost::property_tree.
I use Visual Studio 2010 and boost version 1.48.0.
I do the forward declaration in the following way, in my .h
#ifndef OPTIONS_H_
#define OPTIONS_H_
namespace boost
{
namespace property_tree
{
class ptree;
}
}
class Options
{
// something
private:
boost::property_tree::ptree *m_pxPropertyTree;
};
#endif // OPTIONS_H_
Then, I use the class inside my .cpp
#include <boost/property_tree/ptree.hpp>
using boost::property_tree::ptree;
Options::Options()
{
m_pxPropertyTree = new ptree();
// other stuff
}
when I try to compile it, I obtain the following error
error C2371: 'boost::property_tree::ptree': redefinition. Different base type. c:\lib\boost\1.48.0\32\boost\property_tree\ptree_fwd.hpp 95
(The error description can be different, I've translated it because I've the Italian version of Visual Studio).
The line that gives me the error, in ptree_fwd.hpp, is the following
typedef basic_ptree<std::string, std::string> ptree;
Instead, if I don't use the forward declaration, everything goes well and I compile it successfully.
What I'm doing wrong and how I can use correctly the forward declaration in this case?
Why don't you just include boost/property_tree/ptree_fwd.hpp? This header contains all forward declaration for the package.
Edit: The solution without the included (which you want to avoid for
good reasons) is to exactly match, what is actually declared.
So:
#include <string>
#include <functional>
namespace boost
{
namespace property_tree
{
template < class Key, class Data, class KeyCompare >
class basic_ptree;
typedef basic_ptree< std::string, std::string, std::less<std::string> > ptree;
}
}
i have received in .cpp errors of invalid use of undefined struct PelephonePN, CellcomPN and so on
and also error in .h errors of forward declaration of PelephonePN,...
#ifndef PHONE_H_INCLUDED
#define PHONE_H_INCLUDED
#include <iostream>
#include <ctime>
#include <string>
#include "phone.h"
using namespace std;
class PhoneNumber;
class PelephonePN;
class CellcomPN;
class OrangePN;
class HotPN;
class BezeqPN;
class PhoneManager
{
private:
PelephonePN* mpPelephone;
CellcomPN* mpCellcom;
OrangePN* mpOrange;
HotPN* mpHot;
BezeqPN* mpBezeq;
public:
PhoneManager();
~PhoneManager();
void split_check_data(string str);
};
#endif
and .cpp
#include <iostream>
#include <ctime>
#include <string>
#include <sstream>
#include "phone_manager.h"
#include "phone.h"
using namespace std;
PhoneManager::PhoneManager()
{
srand(time(0));
mpPelephone = new PelephonePN();
mpCellcom = new CellcomPN();
mpOrange = new OrangePN();
mpHot = new HotPN();
mpBezeq = new BezeqPN();
mpPelephone->add(mpCellcom);
mpPelephone->add(mpOrange);
mpPelephone->add(mpHot);
mpPelephone->add(mpBezeq);
mpBezeq->setNext(mpPelephone);
}
To instantiate an object, forward declaration is just insufficient. Include the corresponding headers in the source file. In the body of the constructor, you are instantiating mpPelephone, ..... So, make sure that corresponding class headers can be seen in the translation unit.
In your .cpp source file you need to #include the headers that define class PelephonePN and its associates.
It is fine to forward-declare these classes in the header if you are only using them as pointers or references, but one you start using them in your implementation, you'll need to provide the compiler with the definition.
You can't use a forward declaration of a class to access its members (which includes the constructor, default or otherwise) or its size and without those two things, you can't instantiate an instance of that class.
You require its FULL implementation to do that, so in your .cpp file you need to include the header with the whole class PelephonePN {/* class body */}; section.
in the first file you have lines:
#ifndef PHONE_H_INCLUDED
#define PHONE_H_INCLUDED
I suppose you have same lines in phone.h, please check...
Are your PelephonePN and co. in a particular namespace? If so, predeclarations must all be in the same namespace. Since you added a using namespace std (sigh), my guess is that phone.h is defining your classes inside the namespace std (I hope it doesn't, but that's another thing).
If so, your predeclarations must be:
namespace std {
class PelephonePN;
}
Btw, what is a pelephone??? O.O
With using namespace I make the whole contents of that namespace directly visible without using the namespace qualifier. This can cause problems if using namespace occurs in widely used headers - we can unintendedly make two namespaces with identical classes names visible and the compiler will refuse to compile unless the class name is prepended with the namespace qualifier.
Can I undo using namespace so that the compiler forgets that it saw it previously?
No, but you can tell your coworkers that you should never have a using directive or declaration in a header.
As others said, you can't and the problem shouldn't be there in the first place.
The next-best thing you can do is bring in your needed symbols so that they are preferred by the name look-up:
namespace A { class C {}; }
namespace B { class C {}; }
using namespace A;
using namespace B;
namespace D {
using A::C; // fixes ambiguity
C c;
}
In some cases you can also wrap the offending includes with a namespace:
namespace offender {
# include "offender.h"
}
No, C++ Standard doesn't say anything about "undo". The best you are allowed to do is to limit scope of using:
#include <vector>
namespace Ximpl {
using namespace std;
vector<int> x;
}
vector<int> z; // error. should be std::vector<int>
But unfortunately using namespace Ximpl will bring all names from std namespace as well.
Not to my knowledge... But as a rule I only use "using namespace" in .cpp files.
The closest, that I'll try to use in header files is following:
//example.h
#ifndef EXAMPLE_H_
#define EXAMPLE_H_
/**
* hating c++ for not having "undo" of using namespace xx
*/
#define string std::string
#define map std::map
class Example {
public:
Example (const char *filename);
Example (string filename);
~Example ();
private:
map<string,complicated_stuff*> my_complicated_map;
};
#undef string
#undef map
#endif //EXAMPLE_H_
after all, defines are #undef -able.
There are 2 problems:
1. it is ugly
2. separate #define and #undef for each name from the corresponding namespace are used
As stated you should not use using namespace sth in header files. When you need functionality from a namespace in your implementation you can leverage scopes like this:
void func() {
// some code agnostic to your namespace.
{
using namespace sth;
// some code aware of sth.
}
// some other code agnostic to your namespace.
}