Issue declaring extern class object - c++

Let me start by saying I've extensively searched for answers on google and more specifically here.
The thing is I actually (at least I think I did) found people with similar problems, though the answer given to them gave me another problem.
I'm using Visual Studio 2010 Express and working with SFML libary (though i do not think this last part is relevant)
So here it goes:
I have a source file called player.cpp which holds class Player and I have a header file (included in all source files) called cc.h(command and control) that holds all the necessary includes and external variables/functions. The essential code can be summed up in the following:
Player.cpp:
#include "cc.h"
class Player
{
private:
//some variables here
public:
//more variables and some functions
}john;//example instance
cc.h:
#pragma once
//some #includes
//some externs
extern Player john;
Now in cc.h the word Player is underlined as a mistake saying it is an undefined identifier , but only sometimes, other times visual studio doesn't mark it as a mistake, instead it recognizes it as a class but doesn't recognize john as an object/instance (i hope it's called this way) of that same class.
Furthermore, at compiling the first error it shows is "error C2146: syntax error : missing ';' before identifier 'john'" at the line of the extern declaration of john, in cc.h, which apparently (to me) does not make any sense.

The global declaration in cc.h would not help you, I guess - because you declare it to access it from else where (other than Player.cpp), but for this you need the method signatures - a soon as you want to access john from elsewhere and thus include Player.cpp, you get duplicates symbols.
Please consider creating a Player.h file where only the class and method signatures are declared - like this:
#ifndef PLAYER_H_
#define PLAYER_H_
class Player
{
void doSomething();
};
#endif
and add this to cc.h:
#include <Player.h>
extern Player john;
and in your Player.cpp
#include <Player.h>
Player john;
void Player::doSomething()
{
//...
}
This makes sure that the Player signatures are known and a valid instance is declared globally.

You need to put the definition of your Player class in the header file, before you declare the extern variable. Otherwise the compiler has no idea what Player is.
I suggest something like this:
player.h
#ifndef PLAYER_H_
#define PLAYER_H_
class Player {
...
};
#endif
player.cpp
#include "player.h"
Player john;
cc.h
#ifndef CC_H_
#define CC_H_
#include "player.h"
extern Player john;
#endif

You need to define the Player class, in your header file
Use extern to use variable that has an external linkage, and is already defined in some other file.
For example: you have file a.cpp, and inside this file has a global variable Player p. If you want to use the same exact instance p of Player in file c.cpp, then inside file c.cpp you write extern Player p.
I hope i made myself clear.

"extern Player john;" is considered to be undefined identifier as the compiler is unable to understand what Player is, as you have not included the file Player.cpp where the class Player is declared to cc.h .
It is always recommended to declare the class and its methods in header files say for example in Player.h and then define these methods in the source file i.e Player.cpp.
And to include Player.h in your cc.h so that compiler understands where " Player john;" is declared.

Related

Instant object initialization in C++ fails with LNK2005 error

These are the errors that I've been receiving:
LNK2005 "class Sally TestObject" (?TestObject##3VSally##A) already defined in Source.obj Project2 c:\Users\W8User\documents\visual studio 2015\Projects\Project2\Project2\Source1.obj
and
LNK1169 one or more multiply defined symbols found Project2 c:\users\w8user\documents\visual studio 2015\Projects\Project2\Debug\Project2.exe
I don't really understand where are these errors coming from. I've tried searching in other SO threads or on the connected Microsoft's website, but none helped.
These are my files:
Source.cpp
#include <iostream>
#include "Header.h"
int main() {
std::cout << TestObject.ReturnTruth();
return 0;
}
Header.h
#pragma once
class Sally
{
public:
bool ReturnTruth();
} TestObject;
Source1.cpp
#include "Header.h"
bool Sally::ReturnTruth()
{
return 1;
}
What I know is that it's enough to move the object initialization into the Source.cpp file and not do it instantly in the header file, but since the instant initialization is a possibility then why wouldn't I use it?
Let's suppose that you have two different .cpp files that each include your Header.h header. Then, each one of those .cpp files gets this code incorporated into it:
class Sally
{
public:
bool ReturnTruth();
} TestObject;
As a result, each file contains the definition of an object named TestObject of type Sally. This breaks the one-definition rule, since there's only supposed to be at most one definition of each object across all translation units, and it's manifesting in your linker error.
If you do want to declare a global object of type Sally, change the header to declare an extern object of type Sally, like this:
class Sally
{
public:
bool ReturnTruth();
};
extern Sally TestObject;
This is a declaration, not a definition, and it's okay to have redundant declarations of objects.
Then, pick a .cpp file - probably the one where you implement the Sally member functions - and add this line:
Sally TestObject;
That puts the definition of the object in a single place, and so fixes the one-definition-rule issue and the linker issue.
Every single place you #include "Header.h" you will have an instance of TestObject, and unless your compiler can fold all of these into a singleton you're going to have several independent, unrelated instances.
That error is advising you that you've made a mistake. One way to fix this is to define in the header file:
extern Sally TestObject;
Which makes it explicitly clear that this will be instantiated elsewhere. Then make an explicit instance in Source1.cpp:
Sally TestObject;
Then your main file will know where to look for this thing.
It's not clear if you want a singleton in the first place. Why can't you just instantiate one inside of main and use it?
As a note, please, please take the time to give your source files meaningful names.
By appending identifier TestObject directly after the class definition Sally, you define a variable in your header file. So if different translation units include this header file, a variable with the same name is defined twice, leading to a linker error. You can resolve this by just declaring the variable, i.e. using extern-keyword in the headerfile, whereas defining the variable then in exactly one .cpp-file:
So write:
Header.h
class Sally
{
public:
bool ReturnTruth();
};
extern Sally TestObject;
Source1.cpp
#include "header.h"
Sally TestObject;
...
in all other CPP-files:
#include "header.h"
...

Redefinition Error after moving code into another Header

so i'm having a problem: I cutted out some coding(structs) and pasted it in a new Header-file. I included the new Header-file everywhere it is needed, so it shouldnt get me an error, but after i tried building my dll file, i got tons of errors saying that those structs i cutted out/pasted are redefinitions. I clicked on some of those "redefinitions" and the "originals" and i got to the same struct the same time, meaning there is only one of them so it cant be a redefinition. I'm so confused at the moment and i would really appreciate some help! Thanks in advance :)
EDIT:
i moved this:
struct Game_s
{
bool loaded;
bool FirstUser;
bool AlwaysVerfied;
bool DoingUnlockAll;
int Globaltimer;
int MaxUnlockAll;
time_t t;
};
Game_s Game;
from a Header file called MW2Class.h to another class called Structs.h, looking like this:
#include "stdafx.h"
#include <stdio.h>
#include <string>
#include <xbox.h>
struct Game_s
{
bool loaded;
bool FirstUser;
bool AlwaysVerfied;
bool DoingUnlockAll;
int Globaltimer;
int MaxUnlockAll;
time_t t;
};
Game_s Game;
Your issue is you have a global variable declared in your header file
Game_s Game;
Is going to add Game to every translation unit you include the header in(include guards do not stop this). When you get to the linking stage the linker will see all of theses global variables that are the same and will not know what to do with them.
If you really want the global variable you will need to declare it with extern and define it in one translation unit. For more information on that see: Global variables in header file
Make sure to add the inclusion guard to your headers :
Suppose your header is test_file.hpp, the include guards will be :
#ifndef TESTFILE_HPP_
#define TESTFILE_HPP_
#endif
That prevents multiple inclusions of your header.
Edit :
1 - in your case
#ifndef STRUCTS_H_
#define STRUCTS_H_
#endif

External Linkage in c++

I'm making a simple program dealing with poker hands and probabilities. I'm running test cases on various hands, and in my program I need a deck from which to draw my hand that is constant and global. My program has three main objects: Card, Hand, and Deck. I am trying to create a global deck but it seems no matter what I do I get an error saying globalDeck is undefined in hand.cpp. Here is the relevant code:
hand.cpp:
Hand::Hand(int &one, int &two, int &three, int &four, int &five)
{
cardsinHand.push_back(globalDeck.copy(one));
cardsinHand.push_back(globalDeck.copy(two));
cardsinHand.push_back(globalDeck.copy(three));
cardsinHand.push_back(globalDeck.copy(four));
cardsinHand.push_back(globalDeck.copy(five));
}
and my cardgames.cpp file:
#include "stdafx.h"
#include<iostream>
#include "hand.h"
using namespace std;
Deck globalDeck;
void printresults(long successes, long trials)
......
Note: I have tried replacing Deck globalDeck with extern Deck globalDeck, extern const globalDeck, etc etc. Nothing seems to make it so that globalDeck is defined in hand.cpp. Also, the deck will stay constant throughout the program, so it could be declared as a global constant, or a global variable, whichever is easier. My error output is:
1>c:\users\\desktop\semesters past\winter 2013\computer programming\projects\cardgames\cardgames\hand.cpp(31): error C2065: 'globalDeck' : undeclared identifier
1>c:\users\\desktop\semesters past\winter 2013\computer programming\projects\cardgames\cardgames\hand.cpp(31): error C2228: left of '.copy' must have class/struct/union
1> type is 'unknown-type'
Declare your global variable in one header file
extern Deck globalDeck;
and define it in cardgames.cpp
Deck globalDeck;
Explanation:The compiler has to see what globalDeck is before you can use it. And the compiler mostly processes each *.cpp individually, without looking at others. In header files you can say what things are in the program without giving the complete and unique definition.
The global variable globalDeck needs to be declared in every compilation unit (.cpp file) that uses it. It needs to be defined in exactly one compilation unit.
A declaration of the form
Deck globalDeck;
is both a declaration and a definition. A declaration with extern like:
extern Deck globalDeck;
is just a declaration and not a definition.
Header files (.h files) are just text that is included in other files with #include. So you can put the declaration extern Decl globalDeck; in a header file (any header file) and #include that header file in every .cpp file. You will also need the definition in exactly one .cpp file.
class Deck has not been defined in hand.cpp because a header is missing. You need to add something like #include "hand.h" or #include "deck.h".

C++: almost identical header files, but one gives a peculiar inheritance-related error

For a C++-project, I need to make a game with Doodlebugs and Ants, which are both Organisms. So, I made a class called Organism with the following definition (although I'll probably add way more member functions and member variables, of course).
Organism.h:
#ifndef ORGANISM_H
#define ORGANISM_H
#include "World.h"
class Organism
{
public:
Organism();
~Organism();
virtual void Move() = 0;
friend class World;
int survivalTime;
};
#endif
Organisms live in 'the World', which is a class with (among others) a member variable Organism*** field, a two-dimensional dynamic array containing pointers to Organism objects.
World.h:
#ifndef WORLD_H
#define WORLD_H
#include "Organism.h"
#include "Ant.h"
#include "Doodlebug.h"
class World
{
public:
World();
~World();
void gameplay();
Organism*** field;
};
#endif
You probably already guessed it: Ant and Doodlebug are derived from Organism.
Ant.h:
#ifndef ANT_H
#define ANT_H
#include "Organism.h"
class Ant : public Organism
{
public:
Ant();
~Ant();
void Move();
};
#endif
Doodlebug.h:
#ifndef DOODLEBUG_H
#define DOODLEBUG_H
#include "Organism.h"
class Doodlebug : public Organism
{
public:
Doodlebug();
~Doodlebug();
void Move();
};
#endif
As you can see, Ant.h and Doodlebug.h are almost identical, except for the words Doodlebug and Ant. However, I have two errors.
In World.h, line 16: "'Organism' does not name a type."
In Doodlebug.h, line 7: "expected class-name before '{' token"
Why is this? The first error can be solved by putting class Organism; right before the definition of class World, but I don't understand why that changes anything, since the complete definition of Organism is in Organism.h, which I include.
The second error is the one I'm VERY confused by (and kind of the main reason I'm asking this question), since Ant.h is identical to Doodlebug.h except for the words Ant and Doodlebug, but in Doodlebug.h I get an error but not in Ant.h???
Any help is greatly appreciated.
You have circular dependency between World.h and Organism.h.
World.h has
#include "Organism.h"
and Organism.h has
#include "World.h"
You can remove the above line from Organism.h and replace it with a forward declaration.
class World;
Use forward declaration in header files if you don't need the definition of a as a matter of principle. That will not only avoid problems like the one you encountered but it will also reduce compile time dependecies.
Additional references:
Forward declaration vs include
When can I use a forward declaration?
You did not post your compile command (and most importantly what is the file you try to compile?), but below is what I think your problem is.
The main problem is that your Organism.h includes World.h, which in turn tries to include Organism.h once again, but does not actually include it due to include guards. Therefore, in World.h the compiler still does not know what Organism is and thus generates the first error. You can use forward declaration to solve this: just write
class Organism;
in World.h before class World...; you can also remove #include "Organism.h" from World.h.
I suppose that your second problem can be related to this also.
Note that you can use -E parameter to g++ to generate the file as compiler sees it after preprocessing. Very useful to catch these include-related problems.
The first issue derives from your include "mess". When Organism.h is processed (maybe because a corresponding Organism.cc is compiled) the include statement is replaced by the actual contents, i.e. it is replaced by the contents of World.h. That effectively yields a translation unit where the declaration of World stands before the declaration of Organism, hence leading to the error.
You could also probably remove #include "Organism.h" from your World.h as you have included that in both your Ant and Doodlebug classes, and both of those are included in your World class.

Multiple inclusion in multiple files

I am making a small game.
In BattleRecord.h:
#ifndef _CHARACTER_H_
#define _CHARACTER_H_
#include "Character.h"
#endif
class BattleRecord
{
public:
Character Attacker;
Character Defender;
Status status;
int DamageDealt;
int GoldEarned;
int ExpGained;
};
In Character.h:
#ifndef _EQUIPMENT_H_
#define _EQUIPMENT_H_
#include "Equipment.h"
#endif
class BattleRecord;
class Character
{
BattleRecord AttackEnemy(Character &Enemy);
}
In BattleRecord.h:
#ifndef _CHARACTER_H_
#define _CHARACTEr_H_
#include "Character.h"
#endif
#ifndef _BATLE_RECORD_H_
#define _BATLE_RECORD_H_
#include "BattleRecord.h"
#endif
class GUI
{
public:
//GUI Methods, and two of these:
void ViewStats(Character &Player);
void Report(BattleRecord Record)
}
The problem here is, my Character.h and BattleRecord.h need to include each other, and this definitely will cause multiple redefinition problem. Therefore, I used forward declaration in Character.h by adding:
class BattleRecord;
The problem is sovled. But then, the GUI.h needs BattleRecord.h again for reporting the battle, so I have to include BattleRecord.h into the GUI.h. I also have to include the Character.h in order to pass into the ViewStat function. I got error and stuck with this up to this piont.
You're using inclusion guards wrong. They should appear in the file that you intend to prevent multiple inclusions only, and they should cover the entire file. (not just the includes).
For example, in BattleRecord.h
#ifndef _BATTLE_H_
#define _BATTLE_H_
#include "Character.h"
class BattleRecord
{
public:
Character Attacker;
Character Defender;
Status status;
int DamageDealt;
int GoldEarned;
int ExpGained;
};
#endif // _BATTLE_H_
Put your #endif at the end of the file not the end of your includes or use #pragma once at the top if your compiler supports this although that is less portable.
Edit:
To further explain what #ifdef & ifndef does is tell the compiler to include or exclude code entirely from compilation.
// if _UNQIUEHEADERNAME_H_ is NOT defined include and compile this code up to #endif
#ifndef _UNQIUEHEADERNAME_H_
// preprocessor define so next time we include this file it is defined and we skip it
#define _UNQIUEHEADERNAME_H_
// put all the code classes and what not that should only be included once here
#endif // close the statement
The reason you want to do this is because including a header file is basically saying "put all the code in this file here" if you did that multiple times then you'd have naming conflicts from redefining objects and slow compile times in the best scenario.
In general, use forward declaration instead of includes. This minimizes how many includes you include file contains. The only exception is when the class you are defining is a derived class, then you need to include the base class.
In addition to the include guard issues mentioned above (you also have a _CHARACTEr_H_/_CHARACTER_H_ mismatch that might cause you trouble on line 2 of GUI.h), you may want to revise your object design so that the Character does not AttackEnemy(), but rather there is a Battle() class where two Characters are referenced and a BattleRecord is produced after the battle. This would prevent the Character class from ever having to know about BattleRecords in the first place, would allow for the possibility of multi-Character battles in the future, having multi-turn battles, or having special battles through inheritance of the Battle class.
OK everyone,
Thanks for helping me. I have rewritten all the inclusions for the header files as suggested, and it works flawless now. Take quite time a bit of time since I did it wrong for many classes.