How to use header files for classes? - c++

I'm having trouble creating an OOP version of Hello World. How would I add the World object definition to my header?
Main.cpp:
#include "stdafx.h"
#include "World.h"
#include <iostream>
int main() {
World world;
World world2(5);
std::cin.get();
return 0;
}
World.cpp:
#include "stdafx.h"
#include <iostream>
class World {
public:
World() {
std::cout << "Hello World!" << std::endl;
}
World(int test) {
std::cout << "Hello World!" << std::endl;
}
~World() {
std::cout << "Good Bye!" << std::endl;
}
};
World.h:
class World;
class World(int);
Errors:
1>d:\programming\c++\consoleapplication1\consoleapplication1\world.h(2): error C2062: type 'int' unexpected
1>d:\programming\c++\consoleapplication1\consoleapplication1\main.cpp(6): error C2079: 'world' uses undefined class 'World'
1>d:\programming\c++\consoleapplication1\consoleapplication1\main.cpp(7): error C2079: 'world2' uses undefined class 'World'

Define your class in the header file. You should also definitely use an include guard, to avoid problems when several other files include the same header (not a problem with your current example, but still, it's a very good practice):
// This is the include guard.
#ifndef WORLD_H
#define WORLD_H
class World {
public:
World();
World(int test);
~World();
};
#endif
And define the member functions of that class in the cpp file:
#include "World.h"
#include <iostream>
World::World()
{
std::cout << "Hello World!" << std::endl;
}
World::World(int test)
{
std::cout << "Hello World!" << std::endl;
}
World::~World()
{
std::cout << "Good Bye!" << std::endl;
}
However, you can also define both the class as well the member functions directly in the header file, if you so wish. In that case, you do not need a .cpp file for your class at all. In order to do that, just delete your current World.h header and rename World.cpp to World.h (and add the include guard, as recommended previously.)
Finally, there's a third way you can do this, which also only needs a header file and no .cpp file, where you define the member functions inside the header, but after the class definition by making use if the inline keyword:
#ifndef WORLD_H
#define WORLD_H
#include <iostream>
class World {
public:
World();
World(int test);
~World();
};
inline World::World()
{
std::cout << "Hello World!" << std::endl;
}
inline World::World(int test)
{
std::cout << "Hello World!" << std::endl;
}
inline World::~World()
{
std::cout << "Good Bye!" << std::endl;
}
#endif
This is useful when you don't want the interface of your class to be difficult to read, but still want to be able to do without a .cpp file. Note, however, that not using a .cpp file can increase compilation times when you build a project that includes the header in several different files, and will also trigger a rebuild of all those files if you make even the slightest change in the implementations of the member functions in that header file. Because of this, having a .cpp file for each class is a good idea most of the time, since you can edit that freely without it triggering a rebuild of every other source file that includes the header.

Your header should look like this
#ifndef CLASS_World
#define CLASS_World
class World
{
private:
int m_nValue;
public:
World()
int World(int value)
#endif

Related

Define a static integer in a header with default value

How can I define an integer in a header file so that each cpp file which includes the header will have static const int id=0 while giving the ability to cpps to redefine it with other value.
I tried to used weak symbol but couldn't make it work.
If you are ok with preprocessor definitions you could do this:
// header.h
#ifndef CLASSID
#define CLASSID 0
#endif
static int id=CLASSID;
// class.cpp
#define CLASSID 1
#include "header.h"
This way a source file may override the default, but may also omit it, which is the sort of weak approach you mentioned.
Here's another solution that uses static variables:
// log.h
#ifndef LOG_H
#define LOG_H
#include <iostream>
#define SETLOGID(v) static logidsetter _logidsetter(_logid, v);
#define LOG(v) std::cout << "id: " << _logid << ": " << (v) << std::endl;
class logidsetter
{
public:
logidsetter(int &id, int val)
{
id = val;
}
};
static int _logid = 0;
#endif
// myclass.h
class myclass
{
public:
myclass();
void run(void);
};
// myclass.cpp
#include "log.h"
#include "myclass.h"
SETLOGID(42)
myclass::myclass()
{
LOG("myclass::cons");
}
void myclass::run(void)
{
LOG("myclass::run");
}
// main.cpp
#include "myclass.h"
#include "log.h"
SETLOGID(1)
int main()
{
myclass mc;
LOG("here's main");
mc.run();
}
The log header defines the static int _logid and provides the macro SETLOGID and the class idsetter. The cpp file may use SETLOGID to redefine the static value. This is done with an instantiation of the class idsetter along with the address of _logid and the desired value. The trick allows to bypass C++'s One Definition Rule.
The output looks like:
id: 42: myclass::cons
id: 1: here's main
id: 42: myclass::run

Classes not accessing global objects

This is really puzzling me. For some reason I get a
"c1 not declared in this scope"
error from the compiler. I am usig Mingw with Code::Blocks. I would assume global variables are global to the program? Am I wrong? TYIA -Roland
// main.h
#include <iostream>
#include "classone.cpp"
#include "classtwo.cpp"
extern AnotherClass c2;
extern TheClass c1;
----------
// main.cpp
#include "main.h"
AnotherClass c2;
TheClass c1;
int main()
{
c1.function5();
c2.function2();
return 0;
}
----------
//classone.h
#include "main.h"
class AnotherClass {
`
public:
void function2();
void function3();
private:
int varone;
int vartwo;
};
----------
// classone.cpp
#include "classone.h"
void AnotherClass::function2() {
std::cout << "Function 2 Check\n";
}
void AnotherClass::function3() {
std::cout << "Function 3 Check";
}
----------
// classtwo.h
#include "main.h"
class TheClass {
public:
void function4();
void function5();
};
----------
// classtwo.cpp
#include "classtwo.h"
void TheClass::function4() {
c1.function2();
std::cout << "Function 2 Check\n";
}
void TheClass::function5() {
std::cout << "Function 3 Check";
}
It's quite silly to include .cpp files like that - only include headers.
Anyway, change main.h to this:
#include <iostream>
extern AnotherClass c2;
extern TheClass c1;
Add this to main.cpp:
AnotherClass c2;
TheClass c1;
Then include main.h in each file which needs it, like this:
// classtwo.cpp
#include "classtwo.h"
#include "main.h"
void TheClass::function4() {
c1.function2();
std::cout << "Function 2 Check\n";
}
void TheClass::function5() {
std::cout << "Function 3 Check";
}
Also, you need include guards if you don't have those already.
You need to include the class declarations in your .cpp files if you want to compile all the code in a single file. Inside classtwo.cpp insert #include "classtwo.h" and do the same for classone at the top of both files.
Standard practice is to separate the class code from the client code, so you should compile the classes into a library and link it to the main program.
Your main .h needs to include the .h files of the 2 classes, for it to work. You do not (and should not ) need to include the .cpp files.

why static ofstream doesn't work

I am developing a program in c++ with lots of file io operation. I have defined a static ofstream in a common header so that it is accessible everywhere in the project. The structure of the codes are list as following: all common variable are defined in com.h, test.h and test.cpp are for a class called OPClass, main.cpp carry the main program
COM.H:
#ifndef __CLCOM__
#define __CLCOM__
#include <sstream>
#include <fstream>
#include <iostream>
using namespace std;
static ofstream out;
static stringstream ss;
#endif
TEST.H:
#ifndef __CL__
#define __CL__
#include <iostream>
#include <fstream>
#include "com.h"
using namespace std;
class OPClass
{
public:
void run(void);
void show(ostream &o) const;
};
#endif
TEST.CPP:
#include "com.h"
#include "test.h"
void OPClass::run(void)
{
out << "Here is run()" << endl;
show(out);
}
void OPClass::show(ostream &o) const
{
o << "hello!" << endl;
}
MAIN.CPP:
#include "com.h"
#include "test.h"
void runmain(void)
{
OPClass op;
out.open("output.txt", ios::out | ios::trunc);
out << endl << "State changed!" << endl;
op.run();
if (out.is_open()) out.close();
}
int main(int argc, char* argv[])
{
runmain();
return 0;
}
As you can see, the static ofstream was named as out and will be called in the main program and in the class. I am using mingw32 and didn't see any problem on compilation or upon running. But seems that only the information in runmain() will be written to the output file. Any other message written to that file in the class never appear in the output file. Why's that and how can I written a common file stream so everywhere in the project can access that? Thanks.
Each compilation unit is getting its own ss and out. Hence there is a different instance of them seen by main.cpp than by test.cpp.
You don't really need static here. To address this, rather than declaring the variables and their allocations in the header file you need to merely prototype them using the extern keyword.
#ifndef __CLCOM__
#define __CLCOM__
#include <sstream>
#include <fstream>
#include <iostream>
// Note: don't put "using" statements in headers
// use fully qualified names instead
extern std::ofstream out;
extern std::stringstream ss;
#endif
Where you actually put your declarations is up to you, just make sure it's only in one place. That could be a com.cpp file or you could stick it in main.cpp if that's appropriate for your project.
std::ofstream out;
std::stringstream ss;
Not that global variables like this are a good idea, anyway...
Preemptive statement: You should accept #HostileFork's answer.
Just as an addendum, an easy way to show what's happening is to print out the address of out whenever you try to use it.
If you add these couple statements:
void OPClass::run(void)
{
cout << "Address of 'out' = " << &out << endl;
out << "Here is run()" << endl;
show(out);
}
And:
void runmain(void)
{
cout << "Address of 'out' = " << &out << endl;
OPClass op;
out.open("output.txt", ios::out | ios::trunc);
out << endl << "State changed!" << endl;
op.run();
if (out.is_open()) out.close();
}
You'll notice that the two print statements for out display two different addresses. This should tell you that you're actually getting two instances of out created as two distinct variables. The methods in your OPClass are trying to write to a completely different output stream. It has to do with the way you're using static in a global context; it doesn't behave like you think it does. In a global context, declaring something static binds it to the local scope of the file it's in.

Reference C++ struct object in another file?

I'm in the process of trying to make a game-in-progress more modular. I'd like to be able to declare a single array of all the room_t objects in the game (room_t rooms[]), store it in world.cpp and call it from other files.
The truncated code below does not work, but it's as far as I've gotten. I think I need to use extern but have not been able to find a method that works correctly. If I try and declare the array in the header file, I get a duplicate object error (as each file calls world.h, I'd assume).
main.cpp
#include <iostream>
#include "world.h"
int main()
{
int currentLocation = 0;
cout << "Room: " << rooms[currentLocation].name << "\n";
// error: 'rooms' was not declared in this scope
cout << rooms[currentLocation].desc << "\n";
return 0;
}
world.h
#ifndef WORLD_H
#define WORLD_H
#include <string>
const int ROOM_EXIT_LIST = 10;
const int ROOM_INVENTORY_SIZE = 10;
struct room_t
{
std::string name;
std::string desc;
int exits[ROOM_EXIT_LIST];
int inventory[ROOM_INVENTORY_SIZE];
};
#endif
world.cpp
#include "world.h"
room_t rooms[] = {
{"Bedroom", "There is a bed in here.", {-1,1,2,-1} },
{"Kitchen", "Knives! Knives everywhere!", {0,-1,3,-1} },
{"Hallway North", "A long corridor.",{-1,-1,-1,0} },
{"Hallway South", "A long corridor.",{-1,-1,-1,1} }
};
Just add extern room_t rooms[]; in your world.h file.
world.h
extern room_t rooms[];
The problem is that you're trying to reference a variable you've declared in the .cpp file. There's no handle on this outside of the scope of this file. In order to fix this, why not declare the variable in the .h file but have an Init function:
room_t rooms[];
void Init();
Then in the .cpp
void Init() {
// create a room_t and copy it over
}

C++ class redefinition error

I am compiling a logging program, but I am receiving this error and cant figure it out for the life of me...
logger.cpp:15: error: redefinition of ‘class Logger’
logger.h:20: error: previous definition of ‘class Logger’
with gcc when i compile with
g++ -Wall logger.cpp -o log
logger.h:
#ifndef LOGGER_H
#define LOGGER_H
#include <fstream>
#include <iostream>
#include <string>
using std::string;
class Logger
{
static Logger* m_pInstance;
public:
static Logger* Instance() { return m_pInstance; }
void writeLog(string message);
void openLogFile(string fileName);
void closeLogFile();
void deleteLogger();
};
#endif
logger.cpp
#include "logger.h"
#include <fstream>
#include <iostream>
class Logger
{
static Logger* m_pInstance;
std::ofstream m_pOutputFile;
Logger()
{
}
~Logger()
{
}
public:
static Logger* Instance()
{
if(!m_pInstance)
{
m_pInstance = new Logger;
}
return m_pInstance;
}
void writeLog(std::string message)
{
m_pOutputFile << message << "\n";
std::cout << "you just wrote " << message << " to the log file!\n" << std::endl;
}
void openLogFile(std::string fileName)
{
m_pOutputFile.open(fileName.c_str(),std::ios::out);
}
void closeLogFile()
{
m_pOutputFile.close();
}
void deleteLogger()
{
delete m_pInstance;
}
};
Logger* Logger::m_pInstance = NULL;
It's exactly what the error message says. The implementation file can't just provide a redefinition of the class adding new member variables and conflicting function bodies wherever it pleases. Instead, provide definitions for the functions and static member variables you've already declared.
#include "logger.h"
#include <fstream>
#include <iostream>
static Logger::Logger* m_pInstance;
Logger::Logger()
{
}
Logger::~Logger()
{
}
// this also is illegal, there's a body provided in the header file
//Logger* Logger::Instance()
//{
// if(!m_pInstance)
// {
// m_pInstance = new Logger;
// }
// return m_pInstance;
//}
void Logger::writeLog(std::string message)
{
m_pOutputFile << message << "\n";
std::cout << "you just wrote " << message << " to the log file!\n" << std::endl;
}
and so on
Well, because you are redefining the class. You can't say 'class Logger {' again in the .cpp when you already included it from the .h.
Compiler always expects only one class definition in the whole namespace(or scope) that class belongs to. Currently in the code you specified, you would see that there are infact 2 class definitions: one in .h file and another one in .cpp file. That is why the compiler is complaining that you are redefining a class which is not allowed.
Generally whenever you encounter a compiler error, it's a good idea to look at the lines that compiler tells. Most of the time the problem is in the line the compiler points out.