C++ multiple definition of struct functions - c++

Sorry for the noob question..
devf.h
#ifndef DEVF_H
#define DEVF_H
#include <string>
struct A {
int ax();
std::string ay(std::string jj);
};
struct B {
struct A* f;
int bx() {
return f->ax();
}
std::string by(std::string jj){
return f->ay(jj);
}
};
#endif // DEVF_H
devf.cpp
#include "devf.h"
int A::ax() {
return 5;
}
std::string A::ay(std::string jj){
return jj;
}
I get this error:
multiple definition of `A::ax()'
multiple definition of `A::ay(std::string)'
How can I solve this problem? I want the definitions of ax and ay functions in header file and the implementions in .cpp

Try doing this with your code:
devf.h
#ifndef DEVF_H // Add this line
#define DEVF_H // Add this line
// #include <iostream> // removed this as not needed from what is shown
#include <string> // added this as is needed
struct A {
int ax() const; // added const as it doesn't change
std::string ay( const std::string& jj ) const; // changed string to const ref & added const
};
struct B {
/*struct*/ A* f; // keyword struct not needed here.
int bx() const { // added const
return f->ax();
}
std::string by( const std::string& jj ) const { // changed to const ref & added const
return f->ay( jj );
}
};
#endif // !DEVF_H // Add this line
devf.cpp
#include "devf.h"
int A::ax() const {
return 5;
}
std::string A::ay( const std::string& jj ) const {
return jj;
}
Then you asked this or made this statement:
How can I solve this problem? I want the definitions of ax and ay functions in header file and the implementions in .cpp
devf.h
#ifndef DEVF_H
#define DEVF_H
#include <string>
struct A {
int ax() const;
std::string ay( const std::string& jj ) const;
};
struct B {
A* f;
int bx() const;
std::string by( const std::string& jj ) const;
};
#endif // !DEVF_H
devf.cpp
#include "devf.h"
int A::ax() const {
return 5;
}
std::string A::ay( const std::string& jj ) const {
return jj;
}
int B::bx() const {
return f->ax();
}
std::string B::by( const std::string& ) const {
return f->ay( jj );
}
This should help from what you have shown.
I've tried it with this:
main.cpp
#include <iostream>
#include "devf.h"
int main() {
B b;
std::cout << b.bx() << std::endl;
std::cout << b.by( "hello world" ) << std::endl;
std::cout << "\nPress any key and enter to quit." << std::endl;
char q;
std::cin >> q;
return 0;
}
output
5
hello world
Press any key and enter to quit.
- EDIT
I asked the OP: Are you including other header files?
The OP answered with:
Yes, the header "devf.h" is included in other headers
And I believe this is where the OP's problem resides. I believe that the OP is a victim of Circular Includes which will result in multiple definitions.
Example:
A.h
#ifndef A_H
#define A_H
#include "B.h" // circular include
struct A {
int a;
B b;
};
#endif // !A_H
B.h
#ifndef B_H
#define B_H
#include "A.h" // circular include
struct B {
int b;
};
#endif // !B_H
To resolve this circular include problem...
You need to use class or struct prototypes - forward declarations in the headers; works with pointer & reference types.
Only include other header files within a header file if the definition not the declaration is needed.
Once you have the class or struct's forward declaration in the header file
remove that class's include directive and put it within its cpp file
fixing the above example:
A.h
#ifndef A_H
#define A_H
// Since A has a pointer to B we remove the include from here
// and replace it with a forward declaration or class prototype...
// #include "b.h" // cicular include
class B;
struct A {
int a;
B b;
};
#endif // !A_H
A.cpp
#include "A.h"
#include "B.h" // moved the include to here - prevents circular includes
B.h
#ifndef B_H
#define B_H
// Since B does not require A we can omit this all together.
//#include "A.h" // circular include
struct B {
int b;
};
#endif // !B_H
B.cpp
#include "B.h"
You can refer to this Q & A Resolve build errors due to circular dependency amongst classes on stack for a more detailed explanation.
Once you go through the rest of your code base and fix all of the circular includes you should have no error as the above set of classes do compile and run without error.

Related

How to work with extern in different files

I have these files structure:
main.cpp
#include "main.h"
Map map;
Fruit fruit;
Stone stone;
main.h
extern Map map;
extern Fruit fruit;
extern Stone stone;
map.h
#include "main.h"
class Map {public: int size = 20;};
fruit.h
#include "main.h"
class Fruit { public: int pos = 1; draw() {return map.size;} };
stone.h
#include "main.h"
class Stone { public: draw() {return map.size * fruit.pos;} };
The problem is when I'm trying to use map.size and fruit.pos I get error:
'map': undeclared identifier
The same with stone. So, what's wrong?
main.h should include map.h not the other way around.
main.h should include fruit.h not the other way around.
main.h should include stone.h not the other way around.
Also you should add include guards to your header files.
EDIT
Here's one way that works, (I can't believe I recommending code like this but still)
// map.h
#ifndef MAP_H
#define MAP_H
class Map {public: int size = 20};
extern Map map;
#endif
// fruit.h
#ifndef FRUIT_H
#define FRUIT_H
#include "map.h"
class Fruit { public: int pos = 1; draw() {return map.size;} };
extern Fruit fruit;
#endif
// stone.h
#ifndef STONE_H
#define STONE_H
#include "map.h"
#include "fruit.h"
class Stone { public: draw() {return map.size * fruit.pos;} };
extern Stone stone;
#endif
// main.cpp
#include "map.h"
#include "fruit.h"
#include "stone.h"
Map map;
Fruit fruit;
Stone stone;
This is not how you are supposed to write code.
Files (*.h or *.cpp) should only include files that they directly depend upon.
Files should not include files that they do not depend upon.
One way to break cyclical dependencies is to put the implementation in the foo.cpp source file instead of inline in the foo.h header file.
One way to break dependencies on global variables is to instead pass them in as parameters instead of having them hard-coded into the routines.
Use of a forward declaration can be used to avoid including an header file that is only used to declare the type. Only when the details of the type, such as its methods and footprint, are not important. Alas, forward declarations for template classes are trickier.
For the files in the OP example, here's an alternative implementation incorporating those suggestions.
fruit.h
#ifndef FRUIT_H
#define FRUIT_H
class Map;
class Fruit {
public:
int pos = 1;
auto draw(Map const&) -> int;
};
#endif
map.h
#ifndef MAP_H
#define MAP_H
class Map {
public:
int size = 20;
};
#endif
stone.h
#ifndef STONE_H
#define STONE_H
class Fruit;
class Map;
class Stone {
public:
auto draw(Map const& map, Fruit const& fruit) -> int;
};
#endif
fruit.cpp
// Identity.
#include "fruit.h"
// Other dependencies.
#include "map.h"
auto Fruit::draw(Map const& map) -> int {
return map.size;
}
stone.cpp
// Identity.
#include "stone.h"
// Other dependencies.
#include "fruit.h"
#include "map.h"
auto Stone::draw(Map const& map, Fruit const& fruit) -> int {
return map.size * fruit.pos;
}
main.cpp
#include <iostream>
#include "fruit.h"
#include "map.h"
#include "stone.h"
using std::cout;
int main() {
auto map = Map{};
auto fruit = Fruit{};
auto stone = Stone{};
map.size = 17;
fruit.pos = 3;
cout << "map.size is " << map.size << "\n";
cout << "fruit.pos is " << fruit.pos << "\n";
cout << "fruit.draw(map) is " << fruit.draw(map) << "\n";
cout << "stone.draw(map, fruit) is " << stone.draw(map, fruit) << "\n";
}

Why can't header files include eachother?

Why can't I do something like this in C++?
A.h:
#ifndef A_H
#define A_H
#include "B.h"
struct A {
int a;
};
void doStuff1 (B b); // Error here
#endif
B.h:
#ifndef B_H
#define B_H
#include "A.h"
struct B {
int b;
};
void doStuff2 (A a); // Error here
#endif
I get an error that 'A' was not declared in this scope and the same with 'B'.
I know about forward declaration, but I wanted to see if it was possible to have a set up like this as pass-by-value instead of by reference/pointer. Why does the compiler behave like this, if both A and B are in fact declared by the time the compiler reaches that code?
The basic lesson: Includes are processed before any C++ is parsed. They're handled by the pre-compiler.
Let's say that A.h winds up being included prior to B.h. You get something like this:
#ifndef A_H
#define A_H
// ----- B.h include -----
#ifndef B_H
#define B_H
#include "A.h" // A_H is defined, so this does nothing
struct B {
int b;
};
void doStuff2 (A a); // Error here
#endif
// ----- B.h include -----
struct A {
int a;
};
void doStuff1 (B b); // Error here
#endif
At this point, the C++ compiler can take over and start parsing things out. It will try to figure out what the parameter to doStuff2 is, but A hasn't been defined yet. The same logic holds true going the other way. In both cases, you have dependencies on types that haven't been defined yet.
All of this just means that you have your dependencies out of order. It isn't a problem with pass-by-value. Your types must be defined prior to your methods. That's all - see the example below.
// Example program
#include <iostream>
#include <string>
// data_types.h
struct A
{
int x;
};
struct B
{
int y;
};
using namespace std;
// methods_A.h
void foo(A a)
{
a.x = 3;
cout << "a: " << a.x << endl;
}
// methods_B.h
void bar(B b)
{
b.y = 4;
cout << "b: " << b.y << endl;
}
int main()
{
A first;
B second;
first.x = 0;
second.y = 100;
foo(first);
bar(second);
cout << "A: " << first.x << ", B: " << second.y << endl;
}
Example output
a: 3
b: 4
A: 0, B: 100
You have a circular include. You need to either separate them into different header files, such as having A.h and B.h only declare the struct/classes and having a different header file declare the functions.
The problem can also be solved by using forward declarations and passing by reference instead:
struct A;
struct B;
void doStuff1(A& a);
void doStuff2(B& b);

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

‘Creature’ was not declared in this scope

How to fix error in Hero.h ?
GCC C++ compiler flags : -c -fmessage-length=0 -std=gnu++11 ;
I update g++ to 4.8.1
// Creature.h
#pragma once
#ifndef CREATURE_H_
#define CREATURE_H_
#include <string>
#include "Hero.h"
#include "Characteristics.h"
#include <map>
class Creature
{
private:
CreatureCharacteristics Characters;
Creature(const std::string i_name, int i_count = 0);
Creature(const Creature& Donor);
public:
typedef std::map < std::string, Creature* > Prototypes;
static Prototypes Clones_Bank;
~Creature();
const CreatureCharacteristics& Get_characteristics(){
return this->Characters;
}
static Creature*& Clone(std::string i_name, int i_count = 0);
};
#endif /* CREATURE_H_ */
// Hero.h
#pragma once
#ifndef HERO_H_
#define HERO_H_
#include "Creature.h"
#include "Characteristics.h"
#include <string>
#include <vector>
typedef std::vector<Creature*> Army; // ERROR HERE (‘Creature’ was not declared in this
scope)
class Hero {
private:
Army army;
HeroCharacteristics base_characteristics;
public:
Hero(std::string name = '\0', int attack = 0, int defense = 0):
hero_name(name)
{
base_characteristics.attack = attack;
base_characteristics.defence = defense;
};
const Army& Get_army() const
{
return army;
};
const std::string& Get_name() const
{
return hero_name;
};
const HeroCharacteristics& Get_characteristics() const
{
return base_characteristics;
};
void Add_creature(Creature* creature, int creature_count);
};
#endif /* HERO_H_ */
The problem is that Hero.h and Creature.h include each other: you have a cyclic dependency. When Hero.h includes Creature.h and Creature.h tries to include Hero.h again, HERO_H_ is already defined, and thus nothing gets inserted (if you removed the include guards, you would get an endless include cycle which is no good either).
However, it seems that Creature.h does not actually use Hero.h, so you can just remove this header. If you later do need something from the header, you may very well get away with a forward declaration. For more on this, see the C++ FAQ entry "How can I create two classes that both know about each other?".

Link error after splitting an object definition into .cpp and .h file

The code works fine before I split it into two files with board.h and board.cpp
board.h is given by
#ifndef BOARD_H
#define BOARD_H
#include "Graph.h"
#include "ShortestPath.h"
using namespace std;
enum class boardType : short{SEVEN, ELEVEN};
enum class nodeType : short{UNDEFINED, HUMAN, COMPUTER };
char status2char(nodeType a);
class board{
public:
board{
...
}
~board(){
delete []HexBoard;
}
void printBoard(){
...
}
bool setComputerPosition(int i, char a);
bool setHumanPosition(int i, char a);
private:
nodeType *HexBoard;
Graph Computer;
Graph Human;
int boardSize;
};
#endif /* BOARD_H*/
The board.cpp is like follows;
#include "board.h"
char status2char(nodeType a){
...
}
bool board::setComputerPosition(int i, char a){
...
}
bool board::setHumanPosition(int i, char a){
...
}
All head files have include guards, and the error says the constructor in shortestGraph.h(which is another class) is redefined.
Could you please help me find the problem? Thanks a lot.