I'm writing some code where I need to have a class variable that's a static int array. I understand that I can do this with something like this in the header file, A.h:
#ifndef A_H_
#define A_H_
class A
{
public:
static const int a[];
};
const int A::a[] = {1,2};
#endif
This works just fine if I'm then including this header in only one other file, something like the following, main.cpp:
#include "A.h"
#include <iostream>
using namespace std;
int main()
{
A myA;
cout << "0: " << myA.a[0] << endl;
cout << "1: " << myA.a[1] << endl;
}
But suppose I need my class A to be a bit more complicated, and I want to have an A.cpp file as well. I'll keep my main.cpp file the same, but then change A.h as follows (I've just added a function, printA):
#ifndef A_H_
#define A_H_
class A
{
public:
void printA() const;
static const int a[];
};
const int A::a[] = {1,2};
#endif
And then in file A.cpp:
#include "A.h"
#include <iostream>
using namespace std;
void A::printA() const
{
cout << "Printing in A.cpp." << endl;
cout << "A.0: " << a[0] << endl;
cout << "A.1: " << a[1] << endl;
}
Compiling A.o with gcc -o A.o -c A.cpp is fine. But linking this when compiling main.cpp (gcc -o atest main.cpp A.o) fails with "multiple definition of `A::a'".
I've been scouring the internet for solutions, and found people who have variables declared in their headers who get the "multiple definition" error when they include the header in multiple places, and the solution seems to be to declare the variable extern in the header, then define it in only one source (non-header) source file. But I can't declare a class variable both static and extern, can I? If I try, or if I just declare it extern, I get a warning about the variable not being static (also a "conflicting specifiers" error when I try both).
So, my question: is it possible to have static array class variables in the case that the header file needs to be included in more than one source file? If so, how?
You're violating the one definition rule. Move the definition inside an implementation file:
//A.cpp
#include "A.h"
const int A::a[] = {1,2};
The solution you are reffering to, with extern, applies to non-member variables. In your case a is a class member.
You should remove the "const int A::a[] = {1,2};" line from the header file. Put this definition line in one of you .cpp files.
Then you can include the header file several times where you need it.
Related
I'm writing some code where I need to have a class variable that's a static int array. I understand that I can do this with something like this in the header file, A.h:
#ifndef A_H_
#define A_H_
class A
{
public:
static const int a[];
};
const int A::a[] = {1,2};
#endif
This works just fine if I'm then including this header in only one other file, something like the following, main.cpp:
#include "A.h"
#include <iostream>
using namespace std;
int main()
{
A myA;
cout << "0: " << myA.a[0] << endl;
cout << "1: " << myA.a[1] << endl;
}
But suppose I need my class A to be a bit more complicated, and I want to have an A.cpp file as well. I'll keep my main.cpp file the same, but then change A.h as follows (I've just added a function, printA):
#ifndef A_H_
#define A_H_
class A
{
public:
void printA() const;
static const int a[];
};
const int A::a[] = {1,2};
#endif
And then in file A.cpp:
#include "A.h"
#include <iostream>
using namespace std;
void A::printA() const
{
cout << "Printing in A.cpp." << endl;
cout << "A.0: " << a[0] << endl;
cout << "A.1: " << a[1] << endl;
}
Compiling A.o with gcc -o A.o -c A.cpp is fine. But linking this when compiling main.cpp (gcc -o atest main.cpp A.o) fails with "multiple definition of `A::a'".
I've been scouring the internet for solutions, and found people who have variables declared in their headers who get the "multiple definition" error when they include the header in multiple places, and the solution seems to be to declare the variable extern in the header, then define it in only one source (non-header) source file. But I can't declare a class variable both static and extern, can I? If I try, or if I just declare it extern, I get a warning about the variable not being static (also a "conflicting specifiers" error when I try both).
So, my question: is it possible to have static array class variables in the case that the header file needs to be included in more than one source file? If so, how?
You're violating the one definition rule. Move the definition inside an implementation file:
//A.cpp
#include "A.h"
const int A::a[] = {1,2};
The solution you are reffering to, with extern, applies to non-member variables. In your case a is a class member.
You should remove the "const int A::a[] = {1,2};" line from the header file. Put this definition line in one of you .cpp files.
Then you can include the header file several times where you need it.
I'm writing some code where I need to have a class variable that's a static int array. I understand that I can do this with something like this in the header file, A.h:
#ifndef A_H_
#define A_H_
class A
{
public:
static const int a[];
};
const int A::a[] = {1,2};
#endif
This works just fine if I'm then including this header in only one other file, something like the following, main.cpp:
#include "A.h"
#include <iostream>
using namespace std;
int main()
{
A myA;
cout << "0: " << myA.a[0] << endl;
cout << "1: " << myA.a[1] << endl;
}
But suppose I need my class A to be a bit more complicated, and I want to have an A.cpp file as well. I'll keep my main.cpp file the same, but then change A.h as follows (I've just added a function, printA):
#ifndef A_H_
#define A_H_
class A
{
public:
void printA() const;
static const int a[];
};
const int A::a[] = {1,2};
#endif
And then in file A.cpp:
#include "A.h"
#include <iostream>
using namespace std;
void A::printA() const
{
cout << "Printing in A.cpp." << endl;
cout << "A.0: " << a[0] << endl;
cout << "A.1: " << a[1] << endl;
}
Compiling A.o with gcc -o A.o -c A.cpp is fine. But linking this when compiling main.cpp (gcc -o atest main.cpp A.o) fails with "multiple definition of `A::a'".
I've been scouring the internet for solutions, and found people who have variables declared in their headers who get the "multiple definition" error when they include the header in multiple places, and the solution seems to be to declare the variable extern in the header, then define it in only one source (non-header) source file. But I can't declare a class variable both static and extern, can I? If I try, or if I just declare it extern, I get a warning about the variable not being static (also a "conflicting specifiers" error when I try both).
So, my question: is it possible to have static array class variables in the case that the header file needs to be included in more than one source file? If so, how?
You're violating the one definition rule. Move the definition inside an implementation file:
//A.cpp
#include "A.h"
const int A::a[] = {1,2};
The solution you are reffering to, with extern, applies to non-member variables. In your case a is a class member.
You should remove the "const int A::a[] = {1,2};" line from the header file. Put this definition line in one of you .cpp files.
Then you can include the header file several times where you need it.
I'm have an issue with compiling my program with g++ 8.3. I have approx 10 classes in a program. These classes are placed in header files and their full definitions are in .cpp files. I'm including these classes the same way as in this code:
main.cpp:
#include "CPerson.h"
int main()
{
CPerson person1(10 , "Peter");
CPerson person2(20 , "James");
person1.Print();
person2.Print();
return 0;
}
CPerson.h:
#pragma once
#include <iostream>
#include <string>
using namespace std;
class CPerson{
protected:
int m_Age;
string m_Name;
public:
CPerson( const int age , const char * name ) :
m_Age(age), m_Name(name){}
void Print(){
cout << "Hello Im " << m_Name << " - " << m_Age << "years old" << endl;
}
};
When I try to compile this C++ program with the following command:
g++ main.cpp CPerson.h
I get this message:
warning: #pragma once in main file
Is here anything I can do about this, or is it just bug in the g++ compiler?
SOLVED:
You need to compile only .cpp files with declarations of methods of each class thats defined in Class.h
You get the warning because you are compiling a file that contains #pragma once. #pragma once is only intended to be used in headers, and there is no need to compile headers; hence the warning. Solution: Don't compile headers.
I am trying to define a member struct of a class in a separate file. however, I not sure what is the correct way to implement it.
Below is what I have tried. in code1.cpp is the main source code. I would like to put the definition of the member struct, Mid, to a separate file, code2.cpp. However, in order for code2.cpp know the struct is part of TestCls, I import code1.cpp there and added the guards. I know this is not going to work but I am not sure how to make it work. Thanks
code1.cpp:
#include <iostream>
#include "code2.cpp"
class TestCls {
public:
struct Mid;
};
int main() {
TestCls::Mid mid1;
std::cout << mid1.a << std::endl;
}
code2.cpp
#ifndef XXX
#define XXX
#include <iostream>
#include <sys/dtrace.h>
#include "code1.cpp"
struct TestCls::Mid {
int a = 0;
};
#endif //XXX
Don't include cpp files. Only include header files. While headers files can technically have any (or no) suffix, using source file suffix may end up confusing a build system or compiler to think that it is supposed to be compiled, which you don't want to do with a header. .h or .hpp and few others are commonly used suffixes for headers.
Your code2.cpp includes code1.cpp and code1.cpp includes code2.cpp. Don't have recursive includes like this. While the include guard prevents infinite recursion, this can easily break in some cases.
For a small program like this, as an exercise, I recommend that you first write it entirely into a single file. For example, following would be correct:
class TestCls {
public:
struct Mid;
};
struct TestCls::Mid {
int a = 0;
};
#include <iostream>
int main() {
TestCls::Mid mid1;
std::cout << mid1.a << std::endl;
}
Now, you can slice the file into multiple ones while keeping the order.
// TestCls.hpp
#pragma once
class TestCls {
public:
struct Mid;
};
// TestClsMid.hpp
#pragma once
#include "TestCls.hpp"
struct TestCls::Mid {
int a = 0;
};
// main.cpp
#include "TestCls.hpp"
#include "TestClsMid.hpp"
#include <iostream>
int main() {
TestCls::Mid mid1;
std::cout << mid1.a << std::endl;
}
I used #pragma once for simplicity, buy you can opt for macro guards if you so prefer.
That said, I recommend to reconsider whehter there is any advantage in not defining TestCls::Mid in TestCls.hpp.
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
}