How to fix redefinition error with constants in Header with Namespaces? - c++

I'm a begginer with C++ and I'm trying to practice with headers and Namespaces. Specifically I wanted to create different modules with their own namespaces so I can use one program to go through others without mixing the names. I used the advice from this other question and it works fine with functions but when I get to a constant I get an "redefining error"
The 2 relevant files:
//mainHeader.h
#pragma once
#include <iostream>
#include <string>
#include <sstream>
namespace primes {
int isPrime(int a);
}
namespace CONST {
typedef unsigned long long int LONGINT;
double pi;
}
namespace E1 {
int main();
}
namespace E2 {
int main();
}
//CONSTANTS.cpp
#include "mainHeader.h"
namespace CONST{
pi = 3.14159265;
typedef unsigned long long int LONGINT;
}
Of course there's a main function that is mostly empty and 2 other .cpp files that are working fine. It compiled and worked as wanted before I created the CONSTANTS.cpp and decided to test the same for constants
The problem is that this code tells me that pi in CONSTANTS.cpp isn't defined correctly:
missing type specifier - int assumed. Note: C++ does not support default-int
However, if I add the type to the definition in CONSTANTS
it throws that redefine error.
> e1.obj : error LNK2005: "double CONST::pi" (?pi#CONST##3NA) already defined in CONSTANTS.obj
> e2.obj : error LNK2005: "double CONST::pi" (?pi#CONST##3NA) already defined in CONSTANTS.obj
> e3.obj : error LNK2005: "double CONST::pi" (?pi#CONST##3NA) already defined in CONSTANTS.obj
That sounds like the declaration in mainHeader.h is the problem but if I change it or take it out I get:
> ...\e3.cpp(34): error C2039: 'pi': is not a member of 'CONST'
> ...\mainHeader.h(12): note: see declaration of 'CONST'
> ...\e3.cpp(34): error C2065: 'pi': undeclared identifier
So I don't understand. If I take it out it doesn't find any definition, if I add it, it finds more than one.
The code for e1.cpp just in case, although I think the only problem would be the first line:
#include "mainHeader.h"
namespace E1 {
int main()
{
int ans = 0;
for (int i = 0; i < 1000; i++) {
if ((i % 3 == 0) || (i % 5 == 0)) ans += i;
}
std::cout << ans << std::endl;
return 0;
}
}
I tried what I think is every combination of definition and initialization. I used. I tried adding #pragma once to CONSTANTS.cpp, to e1.cpp, I even tried using
#ifndef CONST_H ... #endif
I added #include "mainHeader.h" to each eX.cpp file because there are functions that I want to share between them. Like for example primes.cpp will have some functions that some eX.cpp files will use, so I need to be able to call them.
Any help will be appreciated

Declare pi as const double and initialize it in header, or if you don't want to declare it as const really then prepend extern to declaration. If you don't do this still it will be extern, but it is also defined as 0.

Related

Visual Studio doesn't accept class implementation [C++]

I'm trying to move from Dev C++ to Visual Studio while studying C++ (since I'll have to work with the latter) but for some reason, a rather simple class implementation that perfectly works in Dev C++ creates a long list of errors in Visual Studio.
The files are simple:
header file, for the declaration of constructors, variables etc
cpp file, to implement said constructors, functions etc
consoleapplication file (on visual studio), to produce the "main()" function.
stock2.h
#ifndef STOCK2_H_
#define STOCK2_H_
class Stock
{
public:
Stock();
Stock(const char* co, int n = 0, double pr = 0.0);
~Stock();
void show()const;
private:
std::string company;
int shares;
double share_val;
double total_val;
};
#endif
stock2.cpp
#include "stdafx.h"
#include <iostream>
#include <string>
#include "stock2.h"
Stock::Stock() //default constructor
{
//code
}
Stock::Stock(const char* co, int n, double pr)
{
//code
}
Stock::~Stock()
{
std::cout << "Stock object has been destroyed" << std::endl;
}
//Methods
void Stock::show() const
{
//code
}
ConsoleApplication.cpp
#include "stdafx.h"
#include "stock2.cpp"
int main()
{
using std::cout;
const int STKS = 4;
Stock stocks[STKS] = {
Stock("NanoSmart", 12, 20.1),
Stock("Boffo Objects", 200, 2.0),
Stock(),
Stock("Monolithic Obelisks", 130, 3.25)
};
cout << "Stock Holdings: \n";
for (int st = 0; st<STKS; st++)
stocks[st].show();
return 0;
}
I've tried to find the solution on other questions posted here but I really can't figure out what's wrong here.
I also read that one is not supposed to #include a cpp file since the header should be the link between the main() and the cpp file itself, but if I decide to use #include stock2.H instead of .CPP in consoleapplication, then the compiler can't find the methods implementations anymore.
EDIT: In the rush i forgot to post the errors!
They're all in this form:
Error LNK2005
"public: void __thiscall Stock::update(double)" (?update#Stock##QAEXN#Z) already defined in
ConsoleApplication1.obj ConsoleApplication1 //path\ConsoleApplication1\ConsoleApplication1\stock2.obj
EDIT2: Since many of you are asking me about the "Solution Explorer", I better just add a screenshot to show you how it's made right now
You included stock2.cpp in your ConsoleApplication.cpp. This means all the code inside stock2.cpp is now compiled twice, and the linker shows the error message
Error LNK2005 "public: void __thiscall Stock::<...> already defined
for the now duplicated functions. Simply replace
#include "stock2.cpp"
with
#include "stock2.h"
If you get another error when doing so, please post the error message for this.

How to declare `#include` for a header file to avoid `error lnk2005`

I created a new WIN32 C++ project. I didn't touch any of the code in the main file yet, and started to write my code in a different file objectsFW.cpp the definitions for the file are located in the file objectsFW.h.
objFW.h looks like:
#pragma once
double g;
typedef struct {
double x;
double y;
}Vector;
typedef struct {
//...
}BoundingBox;
typedef struct {
//...
}Ball;
Vector operator + (Vector a, Vector b) {
//...
}
Vector operator - (Vector a, Vector b) {
//...
}
There are some more operators defined, and the declarations of the functions.
I included the header file in the source file (objectsFW.cpp), and also, added it to the Resources.h file, so that my code will be useable in the main program.
I get linker errors:
Error 1 error LNK2005: "struct Vector __cdecl operator*(struct Vector,double)" (??D#YA?AUVector##U0#N#Z) already defined in ObjectsFW.obj C:\testC\ObjectsCollision\ObjectsCollision\ObjectsCollision.obj ObjectsCollision
...
Error 4 error LNK2005: "struct Vector __cdecl operator+(struct Vector,struct Vector)" (??H#YA?AUVector##U0#0#Z) already defined in ObjectsFW.obj C:\testC\ObjectsCollision\ObjectsCollision\ObjectsCollision.obj ObjectsCollision
and so on.
I know that this happens because the #include "objectFW.h" line appears two times (once in each .cpp file). The question is what is the right way to declare the header file to avoid linker errors?
UPDATE:
After turning the operator functions to inline most of the errors fixed, there is still a program with the line:
double g;
the error is:
Error 1 error LNK2005: "double g" (?g##3NA) already defined in ObjectsCollision.obj C:\testC\ObjectsCollision\ObjectsCollision\ObjectsFW.obj ObjectsCollision
(working on Visual Studio 2012)
About global variables:
1. Refrain from using them. Think encapsulation and data hiding.
2. If you must use them, define the global in 1 source file and place the "extern" in a header file.
Example:
header_file.hpp:
extern unsigned int deadly_global;
source_file.cpp:
unsigned int deadly_global;
Better method for hiding global variables
A better method for controlling (hiding) global variables is to place all the code that uses the variable in the same source file and declare the variable as static:
static unsigned int variable_shared_by_many_functions = 0;
void f1(void)
{
variable_shared_by_many_functions = 42U;
}
void f2(void)
{
std::cout << "Value of shared variable: "
<< variable_shared_by_many_functions
<< "\n";
}
Controlling Global Variables Using Getters and Setters
If you must share the variable among functions in more than one source file, a safer technique is to declare the variable as static in one source file and declare functions (interfaces) to access it.
static int dangerous_variable = 0;
int accessor(void)
{
// Return a copy of the varible.
return dangerous_variable;
}
void setter(int new_value)
{
if ((new_value / 5) != 1)
{
dangerous_variable = new_value;
}
}
This technique allows you to place filters or other controls on setting the variable.
Put in your header:
extern double g;
And in a .cpp:
double g;
That way every file that includes the header will know that there is a variable g, but it will only be declared at one place.

error LNK2005: "int __cdecl number(void)" (?number##YAHXZ) already defined in functions.obj

I think I am having a similar problem to LNK2005, LNK1169 errors, "int __cdecl g(void)" (?g##YAHXZ) already defined but I cannot find the issue.
I am working with Visual Basic and I am having the following files
main.cpp
#include <iostream>
#include "functions.h"
using namespace std;
int main(){
number();
return 0;
}
I had a functions.cpp but after reading the question I linked before I renamed it for functions.h
int number(){
int i = 1;
return i;
}
Now it is displaying error LNK2005: "int __cdecl number(void)" (?number##YAHXZ) already defined in functions.obj
Is there anything wrong with the function number() in functions.h?
You are having linking issues.
Your immediate issue is that the functions.obj contains code that is being linked in. Then you redefine number() in main.cpp so they collide. Go ahead and clean the project (which should delete functions.obj, and you should be able to compile. I, however, recommend doing it this way.
functions.hpp (or functions.h)
int number();
functions.cpp
int number(){
int i = 1;
return i;
}
main.cpp
#include <iostream>
#include "functions.h"
using namespace std;
int main(){
number();
return 0;
}
When you compile, your program will create 2 objects with compiled code functions.obj, and main.obj. Since you use number in the main file, the compiler looks for the implementation of that function. Since the implementation of that function is in the functions.obj object, then you need to link that in.
If you are going to use number() across several C++ files, then you should always separate the code out into its own file and implementation.
functions.h should only declare the functio, as in
int number();
then functions.cpp should contain the function definition
int number(){
int i = 1;
return i;
}
Of course functions.cpp needs to be compiled (add it to the project).
The problem here is that you are including functions.h in multiple files. The issue could be avoided also by simply declaring the function static as in
static int number(){
int i = 1;
return i;
}
However, since it seems you are just learning, I would suggest you to study the basics of compiling c++ code.
In one of the modules you link in there is a function with the name number(). You define you own implementation so the linker does not know which one to use.
Either rename your function or use namespaces.

Problem Initializing an Array in a Global Variables Header File C++

I'm writing a simple program using SDL, but I'm running into a strange problem. First the code:
#ifndef GLOBAL_VARIABLES_H
#define GLOBAL_VARIABLES_H
#include <string>
#include <cassert>
#include "SDL.h"
#include "SDL_image.h"
using std::string;
const int SCREEN_WIDTH = 800;
const int SCREEN_HEIGHT = 600;
const int SCREEN_BPP = 32;
const string MAIN_BACKGROUND_FILENAME = "tempBackground.jpg";
SDL_Rect CARD_CLIPS[2];
const int CARD_BACK = 0;
const int CARD_FRONT = 1;
CARD_CLIPS[CARD_BACK].h = 196;
CARD_CLIPS[CARD_BACK].w = 286/2;
CARD_CLIPS[CARD_BACK].x = 286/2;
CARD_CLIPS[CARD_BACK].y = 0;
CARD_CLIPS[CARD_FRONT].h = 196;
CARD_CLIPS[CARD_FRONT].w = 286/2;
CARD_CLIPS[CARD_FRONT].x = 0;
CARD_CLIPS[CARD_FRONT].y = 0;
#endif
The error I'm getting is this:
1>c:\users\--\global variables.h(23): error C2466: cannot allocate an array of constant size 0
1>c:\users\--\global variables.h(23): error C2143: syntax error : missing ';' before '.'
1>c:\users\--\global variables.h(23): error C4430: missing type specifier - int assumed. Note: C++ does not support default-int
1>c:\users\--\global variables.h(23): error C2371: 'CARD_CLIPS' : redefinition; different basic types
1>c:\users\--\global variables.h(18) : see declaration of 'CARD_CLIPS'
Repeat same error for each time I try to initialize an element of the SDL_Rect.
Note that the SDL part has nothing to do with the problem. If I try to declare an int array and initialize it in the same way, I get the exact same error. If I put any of this in my main.cpp it works completely fine.
Thanks for the help. Let me know if additional information is needed.
EDIT: Note that I get no errors except for when I try and use arrays in the header file. Though I do what to understand the conventional way to do things, I also want to understand why, from a fundamental standpoint, I can't declare and initialize arrays in a header file like this.
First, variable definitions shouldn't be in header files, only extern declarations.
Second, you can initialize variables (including arrays) in the definition, or assign the content as executable statements inside a function. You can't put executable statements at file scope.
Array initialization looks like this:
int a[4] = { 1, 4, 9, 16 };
not like this:
int a[4];
a[0] = 1; // ILLEGAL outside a function!
a[1] = 4;
a[2] = 9;
a[3] = 16;
This article might provide some guidelines on what should be included in a header file.
It says C in the title but of course it's applicable to C++.
As Ben Voigt has already explained, your problem has nothing to do with header files. It is simply that you have put ordinary executable statements that are not declarations, directly at namespace scope (that is, outside any function or class). You can't.
This statement is technically fine:
const int CARD_BACK = 0;
It's technically fine because it is a declaration. There is no assignment. The = here does not denote assignment, but is part of the declaration syntax, indicating that an initializer follows.
I say "technically" because you really should reserve ALL UPPERCASE names for macros, but the compiler doesn't care.
On the other hand, this statement is not OK at namespace scope:
CARD_CLIPS[CARD_BACK].h = 196;
That's because it's not a declaration, it is not introducing a new name: it's an assignment.
Oh, my eyes hurt from all that uppercase!
Cheers,

Resolving "only static const integral data members can be initialized within a class" compilation error

The following for creating a Global Object is resulting in compilation errors.
#include "stdafx.h"
#include <iostream>
using namespace System;
using namespace std;
#pragma hdrstop
class Tester;
void input();
class Tester
{
static int number = 5;
public:
Tester(){};
~Tester(){};
void setNumber(int newNumber)
{
number = newNumber;
}
int getNumber()
{
return number;
}
}
Tester testerObject;
void main(void)
{
cout << "Welcome!" << endl;
while(1)
{
input();
}
}
void input()
{
int newNumber = 0;
cout << "The current number is " << testerObject.getNumber();
cout << "Change number to: ";
cin >> newNumber;
cout << endl;
testerObject.setNumber(newNumber);
cout << "The number has been changed to " << testerObject.getNumber() << endl;
}
Here are the compile errors:
1>------ Build started: Project: test, Configuration: Debug Win32 ------
1>Compiling...
1>test.cpp
1>.\test.cpp(15) : error C2864: 'Tester::number' : only static const integral data members can be initialized within a class
1>.\test.cpp(33) : error C2146: syntax error : missing ';' before identifier 'testerObject'
1>.\test.cpp(33) : error C4430: missing type specifier - int assumed. Note: C++ does not support default-int
1>.\test.cpp(49) : error C2039: 'getNumber' : is not a member of 'System::Int32'
1> c:\windows\microsoft.net\framework\v2.0.50727\mscorlib.dll : see declaration of 'System::Int32'
1>.\test.cpp(55) : error C2039: 'setNumber' : is not a member of 'System::Int32'
1> c:\windows\microsoft.net\framework\v2.0.50727\mscorlib.dll : see declaration of 'System::Int32'
1>.\test.cpp(57) : error C2039: 'getNumber' : is not a member of 'System::Int32'
1> c:\windows\microsoft.net\framework\v2.0.50727\mscorlib.dll : see declaration of 'System::Int32'
1>Build log was saved at "file://c:\Users\Owner\Documents\Visual Studio 2008\Projects\test\test\Debug\BuildLog.htm"
1>test - 6 error(s), 0 warning(s)
========== Build: 0 succeeded, 1 failed, 0 up-to-date, 0 skipped ==========
How do I create a Global Class
Object correctly like I've attempted
here.
And how do I fix that "only static
const integral data members can be
initialized within a class"
And basically how do I fix the rest
of the errors so I can get this to
compile?
I like declaring Global Class Objects at file scope (I like declaring all globals at file scope) because when I have to create separate source files and do "extern" and everything it becomes extremely complicated and never works for me. Although, I do want to figure out how to do that eventually... it seems every tutorial I look at won't compile though and unless it compiles I have no idea how to recreate it!
If I can just get this to compile...then I can successfully learn how to do this. So if someone could rewrite the above to where it literally copies & pastes into Visual C++ Express 2008 and works I will finally be able to figure out how to recreate it. I'm extremely excited on seeing the fix for this! It is just I can't get Global Objects to work right! Any other information on declaring Global Class Objects...or anything for that matter is welcome!
Just start addressing the errors one by one. A lot of the errors are just cascaded from the initial errors, so it looks like there are a lot of problems when there's only a couple. Just start from the top:
1>.\test.cpp(15) : error C2864: 'Tester::number' : only static const integral data members can be initialized within a class
You can't initialize a member in the class definition unless it's static, const, and one of the integral types. Leave the "= 5" off of the declaration of number. Then you'll need to have a definition of Tester::number outside of the class definition, like so:
int Tester::number = 5;
Problem #2:
1>.\test.cpp(33) : error C2146: syntax error : missing ';' before identifier 'testerObject'
Almost exactly what it says (missing semi-colon errors can be a bit inexact in saying where the semicolon should be) - you need a semi-colon after the definition of the Tester class.
Fix those and your compilation problems go away.
The key thing is to try and take compiler errors one at a time from the top. If you get more than about 3 of them, you can probably just ignore everything after the 3rd or so because the initial error just cause the compile to into the weeds (and if they are real errors, they'll show up again in the next compile anyway).
Error C2864: either add a const modifier to your integer, or move the initialization outside the class (as in class Tester { static int number; }; int Tester::number = 5;). The latter seems more appropriate to your case.
Error C2146: you're missing a semicolon after the declaration of class Tester { ... }. It should be class Tester { ... };
The other errors are probably caused by the previous error. They should fix themselves automatically when it is fixed.
As a side note, I don't think you really want the static modifier on your member. It seems more appropriate for an instance field. You still can't initialize it in-place though (this isn't C#), you have to move the initialization to the constructor. For example:
class Tester {
int number;
static int staticNumber; // just to show you how to use a static field
public:
Tester() : number(5) {}
~Tester() {} // I suggest you remove the destructor unless you need it
int getNumber() { return number; }
void setNumber(int value) { number = value; }
static int getStaticNumber() { return staticNumber; }
static void setStaticNumber(int value) { staticNumber = value; }
};
// initialize static members *outside* the class
int Tester::staticNumber = 5;
According to this: http://publib.boulder.ibm.com/infocenter/lnxpcomp/v8v101/index.jsp?topic=/com.ibm.xlcpp8l.doc/language/ref/cplr038.htm
Tester testerObject;
int Tester::number = 5;
I'm not positive, but I think the rest of the errors come from that one problem.
Fix that, and see how far it gets you.
the answers already here deal with why your code doesn't compile and how to correct that. however i am intrigued by your comments about "extern". it is very easy to use when you know how. you declare in one header the extern'ed variable. and then you initialise it in one file. any other file can refer to the variable by including the header. e.g.
header.h:
// ensure the file is only included once
#ifndef _HEADER_H
#define _HEADER_H
extern int foo;
#endif
// end file header.h
header.cpp
#include "header.h"
int foo = 1;
// end file header.cpp
main.cpp
#include "header.h"
#include <stdio.h>
int main(int argc, char** argv)
{
printf("%d", foo);
return 0;
}
// end file main.cpp
Whilst using static class members for global variables helps fit the oo design scheme, its more elaborate than necessary. if you don't have to follow oo strictly, just use extern, its easier and its less code.