Defining member variable in header without class definition - c++

I've got two files, list.cpp and Header.h. Segments of the files are below. I know that if the header file is for a class, it is setup different. E.g.
class MyClass
{
public:
void foo();
int bar;
};
However, since I'm not really working with a class here (correct me if I'm wrong), am I not able to declare things under public: and private like below?
Also, if I were to place the global variable rescan in the header file as a member variable, below the function definitions, only the main function can see the variable. Why is it not within the scope of the other functions?
list.cpp:
#include <boost/algorithm/string.hpp>
#include <vector>
using namespace std;
vector<int> results;
bool rescan;
int main()
{
vector<vector<string>> list;
int success = readFile(list);
vector<vector<string>> bad = findMe(list);
system("pause");
return 0;
}
vector<vector<string>> findMe(vector<vector<string>> find)
{
rescan = true;
}
Header.h:
#pragma once
#ifndef HEADER_H_INCLUDED
#define HEADER_H_INCLUDED
#include <string>
#include <vector>
std::vector<std::vector<std::string>> findMe(std::vector<std::vector<std::string>>);
#endif
EDIT: I tried this in my header file:
public:
bool rescan;
But I got "syntax error: 'public'

If you want your global to be visible in other translation units (TU) (other files), you have to declare them extern in those other TUs:
Header.h:
// Include guard omitted
extern bool rescan; // Declaration
file.cpp
#include "Header.h"
bool rescan = false; // Definition
// ...
file2.cpp
#include "Header.h" // To see extern bool rescan;
void foo()
{
rescan = true;
}
// ...

Related

undefined reference of a function but already defined in header

main cpp
#include "utility.h"
#include <windows.h>
int main()
{
do
{
changeColor();
system("pause");
} while (true);
}
utility cpp
#include "utility.h"
#include "variables.h"
#include <windows.h>
namespace utility
{
void changeColor()
{
if (var::colorCounter == 0)
{
system("color af");
}
else if (var::colorCounter == 1)
{
system("color cf");
}
else if (var::colorCounter == 2)
{
system("color df");
}
else if (var::colorCounter == 3)
{
system("color 6f");
}
else
{
system("color 9f");
var::colorCounter = -1;
}
var::colorCounter++;
}
}
utility header
#ifndef utility
#define utility
void changeColor();
#endif
variables
#ifndef variables
#define variables
namespace var
{
inline int colorCounter{};
}
#endif
idk whats causing it to produce the changeColor() to not define what should i do? also is may coding right?
There are many problems with your code which are shown through the comments in the modified program below.
main.cpp
#include "utility.h"
int main()
{
utility::changeColor();//used utility:: because you've to be in the scope of namespace utility to call function changeColor()
}
utility.h
#ifndef UTILITY_H //USED INCLUDE GUARDS
#define UTILITY_H
namespace utility {
void changeColor(); //this function declaration is now inside the utitliy namespace
}
#endif
variables.h
#ifndef VARIABLES_H //USED INCLUDE GUARDS
#define VARIABLES_H
namespace var
{
//NOTE the extern keyword here instead of inline keyword
extern int colorCounter; //this is a nondefininig declaraiton for colorCounter.
}
#endif
variables.cpp
#include "variables.h"
namespace var
{
int colorCounter = 0; //this is definition of colorCounter
}
The output of the above program can be seen here.
Modifications
Some of the modifications that i made include:
In main.cpp, you have to be in the scope of the namespace utility to call function changeColor(). This is achieved using utility::.
In utility.h, header guards are used. This is a recommended practice.
In utility.h, the function declaration for changeColor is placed inside the namespace utility.
In variables.h, extern keyword is used instead of inline keyword to make the declaration of colorCounter a declaration that is not a definition. This essentially means, colorCounter has external linkage.
In variables.cpp, the variable colorCounter has been initialized with value 0.
Note
If you still want to use inline instead of extern you can do so from C++17 and onward as can be seen here. So if you use inline your program will work for C++17 and onwards. But if you use extern as in my above code, then your program will work in all C++ versions. You can choose whichever version you want.

C++ error: incomplete type used in nested name specifier

I have the following header helper.h:
#ifndef ADD_H
#define ADD_H
class Helper{
public:
static float calculateSpriteSize(float imgSize, float screenSize);
};
#endif
This is my helper.cpp:
#include "block.h"
#include "helper.h"
float Helper::calculateSpriteSize(float imgSize, float screenSize)
{
return ((imgSize/screenSize)*100);
}
But, for some reason, when I call my function calculateSpriteSize on my running code by doing:
#include "header.h"
int main(void){
float h = Helper::calculateSpriteSize( 168.0f, 170.0f );
)
I get the following error:
error: incomplete type 'Helper' used in nested name specifier
Any help would be appreciated.
Block.h looks as follows:
#ifndef ADD_H
#define ADD_H
class Block{
private:
int imgID;
int life;
float price;
public:
Block();
void setImgID(int imgID);
int getImgID();
};
#endif
And block.cpp looks as follows:
#include "block.h"
Block::Block()
{
}
void Block::setImgID(int imgID)
{
this->imgID = imgID;
}
int Block::getImgID()
{
return imgID;
}
UPDATE: I added Helper to the class definition as suggested by Rakete1111. This did not fix the issue though.
UPDATE 2: Changed forward declaration to include. Added other include that was in my code in case its important.
The type introduced by forward declaration is incomplete type. But member function invoking requires the type to be complete, otherwise how does the compiler know whether the member exists or not, and its signature?
You need to include the header file.
#include "helper.h"
int main(void){
float h = Helper::calculateSpriteSize( 168.0f, 170.0f );
)
EDIT
You're using the same macro ADD_H in both "block.h" and "helper.h". It means for
#include "block.h"
#include "helper.h"
the second including would fail, the content of helper.h won't be included at all.
Change the including guard macro name to be unique, better to make it conform to the name of file name. Such as HELPER_H and BLOCK_H.

Static variable link error, C++

Consider this code.
//header.h
int x;
//otherSource.cpp
#include "header.h"
//main.cpp
#include "header.h"
...
int main()
{
}
In this case compiler erred with the message. "fatal error LNK1169: one or more multiply defined symbols found"
but when I add static before x, it compiles without errors.
And here is the second case.
//header.h
class A
{
public:
void f(){}
static int a;
};
int A::a = 0;
/otherSource.cpp
#include "header.h"
//main.cpp
#include "header.h"
...
int main()
{
}
In this case compiler again erred with multiple declaration.
Can anybody explain me the behavior we static variables in classes and in global declarations?? Thanks in advance.
The issue with the static member variable is that you have the definition occur in the header file. If you #include the file in multiple source files, you have multiple definitions of the static member variable.
To fix this, the header file should consist only of this:
#ifndef HEADER_H
#define HEADER_H
// In the header file
class A
{
public:
void f(){}
static int a;
};
#endif
The definition of the static variable a should be in one and only one module. The obvious place for this is in your main.cpp.
#include "header.h"
int A::a = 0; // defined here
int main()
{
}
Declare x as extern in header.h to tell the compiler that x will be defined somewhere else:
extern int x;
Then define x once in the source file which you think is most fitting.
For example in otherSource.cpp:
int x = some_initial_value;

C++ using booleans across multiple files

//main.cpp
#include <iostream>
#include "worldActions.h"
using namespace std;
bool worldEvents = false;
void worldReactions(bool world);
int main (int argc, const char * argv[])
{
while (true)
{
if (worldAction == true)
{
worldEvents = true;
worldReactions(worldEvents);
}
else
{
worldEvents = false;
break;
}
}
return 0;
}
//1.cpp
#include <iostream>
#include "worldActions.h"
using namespace std;
bool worldAction;
//header
#ifndef worldActions_h
#define worldActions_h
bool worldAction = true;
#endif /* defined(__asdf_Story__worldActions__) */
When ever extern is used I get linking errors and when it's not I get redefinition errors. How can I fix this so I can use a global boolean?
You use extern bool worldAction; in the header and put the definition in the cpp file.
You are currently compiling a global worldAction into each file which includes your header. If more than one file includes the header or (as in your source file) any other file defines a variable with the same name, you'll get linker errors.
To fix this, change your header to declare the variable only
#ifndef worldActions_h
#define worldActions_h
extern bool worldAction;
#endif /* defined(__Julian_Story__worldActions__) */
and define/initialise it in your source file
#include <iostream>
#include "worldActions.h"
using namespace std;
bool worldAction = true;
use keyword externlike extern bool worldAction; & put definition bool worldAction = true in .cpp file

Redefinition of class

I got three .cpp files and two header files.
But when i compile them, meaning the Point.cpp, Data.cpp and main.cpp, it will say
Data.h:6:7 redefinition of Data at 'Data.h'
Data.h:6:7 previously definition of 'class Data'
Below is my Data.h(previously known as 2.h at above)
#include <iostream>
#include <string>
using namespace std;
class Data
{
private:
string sType;
public:
Data();
Data(string);
void setSType(string);
string getSType();
};
Below is my data.cpp
#include "Data.h"
Data::Data()
{
sType = "";
}
Data::Data(string s)
{
sType = s;
}
void Data::setSType(string ss)
{
sType = ss;
}
string Data::getSType()
{
return sType;
}
Below is my PointD.h (previously known as 3.h)
#include <iostream>
#include <string>
#include "Data.h"
using namespace std;
class PointD
{
private:
int x
Data data1;
public:
PointD();
PointD(int,Data);
void setX(int);
void setData(Data);
int getX();
Data getData();
};
Below is my PointD.cpp
#include "PointD.h"
PointD::PointD()
{
x = 0;
}
PointD::PointD(int xOrdinate,Data dd)
{
x = xOrdinate;
data1 = dd;
}
void PointD::setXordinate(int Xordinate)
{
x = Xordinate;
}
void PointD::setData(Data dd)
{
data1 = dd;
};
int PointD::getXordinate()
{
return x;
}
Data PointD::getData()
{
return data1;
}
This is my main.cpp
#include <iostream>
#include <string>
#include "Data.h"
#include "PointD.h"
using namespace std;
int main()
{
const int MAX_NUM = 20;
Data ldata[MAX_NUM];
PointD pointd[MAX_NUM];
//more codes..
}
But when i compile them, meaning the Point.cpp, Data.cpp and main.cpp, it will say
Data.h:6:7 redefinition of Data at 'Data.h'
Data.h:6:7 previously definition of 'class Data'
Can anybody let me know whats actually went wrong here..
You need to use include guards, or the easiest:
#pragma once
in your header files
See Purpose of Header guards for more background
Idea: 1.hpp
#ifndef HEADER_GUARD_H1_HPP__
#define HEADER_GUARD_H1_HPP__
// proceed to declare ClassOne
#endif // HEADER_GUARD_H1_HPP__
In each of your header files write:
#ifndef MYHEADERNAME_H
#define MYHEADERNAME_H
code goes here....
#endif
Its better like this:
#ifndef DATA_H /* Added */
#define DATA_H /* Added */
#include <iostream>
#include <string>
// using namespace std; /* Removed */
class Data
{
private:
std::string sType;
public:
Data();
Data( std::string const& ); // Prevent copy of string object.
void setSType( std::string& ); // Prevent copy of string object.
std::string const& getSType() const; // prevent copy on return
std::string& getSType(); // prevent copy on return
};
#endif /* DATA_H */
The big fix is adding ifndef,define,endif. The #include directive works as if copying and pasting the .h to that line. In your case the include from main.cpp are:
main.cpp
-> Data.h (1)
-> Point.h
-> Data.h (2)
At (2), Data.h has already been `pasted' into main.cpp at (1). The class declaration of Data, i.e. "class Data{ .... };" , appears twice. This is an error.
Adding include guards to the top and bottom of every .h are standard practice to avoid this problem. Don't think about it. Just do it.
Another change I'd suggest is to remove any "using namespace ..." lines from any .h . This breaks the purpose of namespaces, which is to place names into separate groups so that they are not ambiguous in cases where someone else wants an object or function with the same name. This is not an error in your program, but is an error waiting to happen.
For example, if we have:
xstring.h:
namespace xnames
{
class string
{
...
};
}
Foo.h
#include <xstring>
using namespace xnames;
...
test.cxx:
#include "Foo.h"
#include "Data.h" // Breaks at: Data( string ); -- std::string or xnames::string?
...
void test()
{
string x; // Breaks. // std::string or xnames::string?
}
Here the compiler no longer knows whether you mean xnames::string or std::string. This fails in test.cxx, which is fixable by being more specific:
void test()
{
std::string x;
}
However, this compilation still now breaks in Data.h. Therefore, if you provide that header file to someone, there will be cases when it is incompatible with their code and only fixable by changing your header files and removing the "using namespace ...;" lines.
Again, this is just good coding style. Don't think about it. Just do it.
Also, in my version of Data.h, I've changed the method parameters and return types to be references (with the &). This prevents the object and all of its state from being copied. Some clever-clogs will point our that the string class's is implementation prevents this by being copy-on-write. Maybe so, but in general, use references when passing or returning objects. It just better coding style. Get in the habit of doing it.