Avoiding redeclaration for header to source file - c++

Let's say I have two files foo.h and foo.cpp
foo.h
class foo
{
public:
Foo();
~Foo();
private:
/*
Member functions
*/
static void DoThis();
/*
Member variables
*/
static int x;
protected:
};
foo.cpp
#include "foo.h"
int foo::x;
void foo::DoThis()
{
x++;
}
Can I avoid the hassle of having to declare each variable in foo.cpp again? If I removed this line int foo::x; I would get a linker error for unresolved external symbol.
Is there another way of doing this without having to type a line for each variable I'm planning to use?

You only need to re-declare static variables. If you make a variable in the class definition without making them static, you can just leave them there. Example:
foo.h
#ifndef _FOO_H_
#define _FOO_H_
class Foo{
private:
static int i; //Static variable shared among all instances
int o; //Non-static variable remains unique among all instances
public:
Foo(); //Consructor
};
#endif
foo.cpp
int Foo::i = 0; //Only static variables can be initialized when in a class
//No definition required for non-statics
Foo::Foo(){
//Constructor code here
i = 0;
};
The #ifndef block prevents the header from accidentally being included multiple times by the same source file. This is in case a header is included in another header, which, if these blocks are not present, could result in an infinite include loop and force the compiler to quit when it counts an include depth that's too high.

Related

Can you use the pimpl idiom for use across multiple cpp files with one class?

For instance, here is what I mean. Let's say you have a single header file with a single pimpl class. Can you define the functions of this class across two cpp files without redefining the variables of the class?
I've tried this before using a static variable for the pointer and a redefinition in both files. I keep running into issues regarding class variables being erased when moving across files, however.
//Header
class PRIVATE {
struct Test2;
public:
struct Test;
std::shared_ptr<Test> Client_ptr;
PRIVATE();
}; //PRIVATE
static std::shared_ptr<PRIVATE> PB = std::shared_ptr<PRIVATE>();
//Cpp1
//Implementation for Private
//Implementation for Test1
//Function not inside either class, references PB, defined in Cpp2 -> READ ACCESS VIOLATION
//Cpp2
//Definition Goes Here
//Implementation for Test2
//Function not inside either class, references PB, defined in Cpp1 -> READ ACCESS VIOLATION
Usually with this kind of thing, you'd have a public header, e.g.
#pragma once
class Foo {
Foo();
~Foo();
private:
struct FooPimpl;
FooPimpl* pimpl;
};
Then you'd have a second private header file (typically in your source directory, rather than include dir). The private header would define your Pimpl struct type.
#pragma once
struct Foo::FooPimpl {
/*stuff*/
};
You'd need to declare your ctors / dtors somewhere, e.g.
Foo.cpp
#include "public/Foo.h"
#include "./Foo.h"
Foo::Foo() {
pimpl = new FooPimpl;
}
Foo::~Foo() {
delete pimpl;
}
And you can use that same pattern (e.g. include public header, then private header) for all your other source files.
One issue with splitting pimpl internals across separate compilation units is that you need at least one compilation unit that knows how to destroy all members.
For example:
//main.h
class Main {
struct Test;
struct Test2;
std::unique_ptr<Test> pimpl1;
std::unique_ptr<Test2> pimpl2;
public:
Main();
~Main();
};
//test1.cpp
struct Main::Test {
};
// we don't know what Test2 is, so we cannot define Main::~Main().
//test2.cpp
struct Main::Test2 {
};
// we don't know what Test is, so we cannot define Main::~Main().
One solution is this:
class Main {
struct Test;
struct Test2;
std::unique_ptr<Test> pimpl1;
struct Defer {
std::unique_ptr<Test2> pimpl2;
Defer();
~Defer();
};
Defer defer;
public:
Main();
~Main();
};
Now, Main::Defer::~Defer() can live in test2.cpp where it knows how to destroy its pimpl2 instance but doesn't need to know how to destroy pimpl. Similarly, since Main::Defer is defined (not just declared) in main.h, Main::~Main() can properly destroy its defer member:
//test1.cpp
/* Test definition */
Main::Main() : pimpl(std::make_unique<Test>()), defer() {}
Main::~Main() {}
//test2.cpp
/* Test2 definition */
Main::Defer::Defer() : pimpl2(std::make_unique<Test2>()) {}
Main::Defer::~Defer() {}
It's still difficult to have Test and Test2 talk between each other but that is kind of the point of pimpl. It can be facilitated by Main offering some interfaces or by some intermediate header that declares some interfaces.

functions that intake objects belonging to classes in other files

Why if I have
in foo.h:
class Foo
{
}
void Bar(const Foo& foo);
it works but:
in foo.h:
class Foo
{
}
in bar.cpp
#include "foo.h"
void Bar(const Foo& foo);
doesn't work (unknown type name 'Foo' is its exact words)?
I don't know what about my question isn't specific and forward declarations don't work they just create a error 'duplicate symbol' so im just going to post the code im working with
in creatures.h
#ifndef CREATURES_H_
#define CREATURES_H_
#include <string>
#include "textio.hpp"
class Creature {
private:
protected:
int statBlock[10];
public:
std::string name = "foo";
Creature ();
void ai(int);
};
class Dwarf : public Creature {
private:
public:
std::string name = "Dwarf";
Dwarf (int);
void defaultDwarfGen();
};
main.cpp
#endif
#include "creatures.hpp"
#include "textio.hpp"
#include <iostream>
int main(int argc, char const *argv[]) {
Dwarf creature_1(0);
return 0;
}
textio.hpp:
#ifndef TEXTIO_H
#define TEXTIO_H
#include <iostream>
#include "creatures.hpp"
void challenge(const Creature& param);
#endif
Your problem is that you are including textio.hpp in creatures.hpp so first time that compiler see function void challenge(const Creature& param)Creature class isn't defined.
When you include createures.hppin textio.hpp CREATURES_H_ is already defined and bypass inclusion)
You can fix it deleting this include or declaring a forward definition for Creature class
In order to answer this question properly, you must provide foo.h, foo.cpp, bar.h, and bar.cpp
In short:
To make use of Bar in foo.h, foo.h must have the declaration for Bar.
To make use of Foo in bar.h, bar.h must have the declaration for Foo.
To make use of Bar in foo.cpp, foo.h or foo.cpp must have the declaration for Bar.
To make use of Foo in bar.cpp, bar.h or bar.cpp must have the declaration for Foo.
When I say, "must have declaration for", you can #include the appropriate header.
If you are trying to use Foo in Bar and Bar in Foo, then you've got a circular reference. The way we overcome this is with a forward declaration.
You can read about forward declarations here: https://isocpp.org/wiki/faq/misc-technical-issues#forward-decl

How and where to define class variable when using header files in C++

/*
* CDummy.h
*/
#ifndef CDUMMY_H_
#define CDUMMY_H_
class CDummy {
public:
CDummy();
virtual ~CDummy();
};
#endif /* CDUMMY_H_ */
I've read that one should not declare class variables in header files. ist this right?
So I declare it in the cpp file below:
/*
* CDummy.cpp
*/
#include "CDummy.h"
static int counter = 0; //so here is my static counter. is this now private or public? how can i make it public, i cannot introduce a public block here.
CDummy::CDummy() {
counter++;
}
CDummy::~CDummy() {
counter--;
}
using this code i cannot access the classvariable from my main program....
thx
A "class variable" needs to belong to a class. So it has to be declared in the class definition. If the class definition is in a header file, then it follows that the class variable declaration must also be in a header file.
The class variable's definition should go in an implementation file, typically the one in which the class' members are defined. Here's a simplified example:
Foo.h
struct Foo
{
void foo() const;
static int FOO; // declaration
};
Foo.cpp
void Foo::foo() {}
int Foo::FOO = 42; // definition
What you have here:
static int counter = 0;
is a static variable that is not a static member of any class. It is only non-member static variable, static to the compilation unit of CDummy.cpp.
static int counter = 0; //so here is my static counter. is this now private or public? how can i make it public, i cannot introduce a public block here.
From the code I see counter is just a global static variables as it is not declated anywhere in your CDummy
Static variables should be public so that you could initialize them outside the class declaration. Your code should look like this to have it public:
class CDummy {
public:
static int count;
CDummy();
virtual ~CDummy();
};
// inside CDummy.cpp
int CDummy::count = 0;
Here you can read more about how to use static variables in class declaration.

Unable to inline functions even if put in header c++

I am having trouble inlining member functions. My code is as follows:
Main.cpp
#include "Foo.h"
int _tmain(int argc, _TCHAR* argv[])
{
Foo foo;
int a = foo.myInlinedFunc(2);
}
Foo.h
class Foo
{
public:
Foo(void);
~Foo(void);
inline int myInlinedFunc(int value);
};
Foo.cpp
#include "Foo.h"
Foo::Foo(void)
{
}
Foo::~Foo(void)
{
}
int Foo::myInlinedFunc(int value)
{
return value * value;
}
I get the following error:
Tester.obj : error LNK2019: unresolved external symbol "public: int __thiscall Foo::myInlinedFunc(int)" (?myInlinedFunc#Foo##QAEHH#Z) referenced in function _wmain
1>E:\Debug\Tester.exe : fatal error LNK1120: 1 unresolved externals
I have searched google for answers, but the only answers that show up, tells me that I should put the inline keyword in the header-file where it already is.
You need to put the function body, i.e. the definition, in the header file.
Your header needs to read like this:
Foo.h
class Foo
{
public:
Foo(void);
~Foo(void);
inline int myInlinedFunc(int value)
{
return value * value;
}
};
And naturally you also have to remove the definition of myInlinedFunc from Foo.cpp.
Or, if you prefer, you can write your header code like this:
Foo.h
class Foo
{
public:
Foo(void);
~Foo(void);
int myInlinedFunc(int value);
};
inline int Foo::myInlinedFunc(int value)
{
return value * value;
}
But the bottom line is that if you need your function inlined, and available to other translation units, its definition must be placed in the header file.
The C++ FAQ explains this and even predicts your unresolved external error.
If you want to share the inlined function (be usable outside the class it is in), the function must must go into the header. It doesn't need to go into top part of the header. Put it outside of the class declaration but in the same *.h file.
The source of functions' definitions need to be available for the compiler if you want to have them inlined. You can keep it in the header, or have it in a .cpp file which you include in the header.
For example, this would be Foo.h
#ifndef Foo_h
#define Foo_h
class Foo
{
public:
Foo(void);
~Foo(void);
inline int myInlinedFunc(int value);
};
#include "Foo.cpp"
#endif Foo_h
You can keep definition of the function in Foo.cpp
inline int Foo::myInlinedFunc(int value)
{
return value * value;
}
To use the class just include Foo.h where you need it. You don't need to compile Foo.cpp separatly.
You can do 1 of 2 ways
Put definition of the inline function (in your example is myInlinedFunc) in the header file
If you want to put definition of the function in another file, let add the following line at the end of the header file
#include "Foo.cpp"
And in Foo.cpp, add this line at the top of file
#include "Foo.h"

define static function outside the class and access static value .h and .cc files

//foo.h
class Foo
{
private:
static int number;
public:
static int bar();
};
//foo.cc
#include "foo.h"
int Foo::bar()
{
return Foo::number;
}
this is not working. I want to define a static function outside the class definition and access a static value.
undefined reference to `Foo::number'
You just declared the static member you need to define it too.
Add this in your cpp file.
int Foo::number = 0;
This should be a good read:
what is the difference between a definition and a declaration?
you have to define Foo::number:
// foo.cc
...
int Foo::number(0);
You have declared Foo::number you have to add a definition. In your cpp file Add this line
int Foo::number = 0;