I want to include the definition and implementation of a C++ class in a header file.
I'm creating a library that need to be C-compatible. The .h file defines a C++ class that can be subclassed for easy C++-style access to the library. It is internally used in the library as well.
As the header file is imported into several subclasses, I always get the "multiple definition" error. Because the class definition should be importable for users of the library, I do not want to move the implementation in a separate cpp file.
Do you have any idea how this problem can be solved?
simplified example:
//library:
typedef struct IFoo{
virtual void foo = 0;
};
void library_fun_a(IFoo*);
void library_fun_b(IFoo*);
//header file
#pragma once
class FooWrapper : public IFoo{
virtual void foo() override;
};
void FooWrapper::foo(){
//some magic here
}
[Edit] Using include guards doesn't help to stop the compile from including the implementation in all object files and therefore the linker to encounter the "multiple definition" error.
You must use include guards which are essentially just macros that determine if the compiler has already included the interface or whatever contents are in the header file.
For example
#ifndef FOO_WRAPPER_H
#define FOO_WRAPPER_H
// header contents here ...
#endif // !FOO_WRAPPER_H
If you're using a Microsoft compiler, you can use the directive #pragma once at the top of the header file. Note that this breaks compatibility with other compilers.
You can easily solve your multiple defintion problem when you inline your code correctly:
class FooWrapper : public IFoo {
virtual void foo() override {
//some magic here
}
};
Related
I have an interface ver as
// ver.h
class ver
{
public:
virtual void func()=0;
};
Then ver1 and ver2 implement this interface. ver1 and ver2 differ in the sense they include header test\header.h and test2\header.h. Now test\header.h and test2\header.h are not under my control and are mostly similar except for a function pointer which is the reason for having ver1 and ver2
// test\header.h
#ifndef header
#define header
typedef void
(*FuncPoint)(
struct_type_a
);
#endif
and
// test2\header.h
#ifndef header
#define header
typedef void
(*FuncPoint)(
struct_type_b
);
#endif
Now the implementations
//ver1.h
#include "test\header.h"
class ver1:public ver
{
public:
FuncPoint f;
};
and
//ver2.h
#include "test2\header.h"
class ver2:public ver
{
public:
FuncPoint f;
};
and ver1.cpp and ver2.cpp will be using the respective f
Now the polymorphic behavior comes into play here
//something.cpp
#include "ver.h"
#include "ver1.h"
#include "ver2.h"
ver* somefunc()
{
if (some_condition)
return new ver1();
else
return new ver2();
}
Since something.cpp includes both ver1.h and ver2.h, first test\header1.h gets included and because of the include guards, test\header2.h is not included and hence there is no FuncPoint defined for class ver2 and something.cpp fails to compile.
On the other hand ver1.cpp and ver2.cpp gets compiled successfully since there is only one header.h included.
I could do a #undef header after including ver1.h in something.cpp but that would give redefinition error for other things which are same in test\header.h1 and tes\header2.h.
A simple fix would be to not have FuncPoint f as global variables instead of member variables, this way i won't have to include test\header.h in ver1.h but instead in ver1.cpp.
Is there some other better way to fix this?
EDIT:
I could forward declare struct_type_a and struct_type_b in something.cpp and avoid including ver1.h and ver2.h in something.cpp. But class ver1 and ver2 use other things(to declare members) from test\header.h as well(which are same in both versions).
Don't include header.h in ver1.h or ver2.h but in the respective .cpp files: FuncPoint is a pointer so you can use forward declarations. Since ver1.h and ver2.h will both be included you will need to rename it however where exposed (in the .cpp files you will be able to use the original FuncPoint too, since you include only one definition of it there):
//ver1.h
#include "ver.h"
struct struct_type_a;
typedef void (*FuncPoint_a)(struct_type_a);
class ver1 : public ver
{
public:
FuncPoint_a f;
static ver1 *create();
};
Also the creation of the polymorphic objects must be demanded to methods implemented in the .cpp files, in the create() static method.
Following your code it would become:
//something.cpp
#include "ver.h"
#include "ver1.h"
#include "ver2.h"
ver* somefunc()
{
if (some_condition)
return ver1::create();
else
return ver2::create();
}
In this way the two colliding headers will never be included in the same file.
I've added the inclusion of ver.h in ver1.h (and ver2.h) because this is the source using it. Including it in something.cpp only is not correct (ver1 and ver2 need it) - but not related to the current problem.
We are working on two C++ code base, let's call it A and B, the A is an build as an library, and distribute the header files .h and .a file to B.
Let's say there is Lock.h file in A as following:
// Lock.h in code base A
class Lock {
... ...
#ifdef TRACK_THREAD_OWNER_FOR_DEBUG
virtual int GetLockOwner();
#endif
... ...
private:
CriticalSection section;
#ifdef TRACK_THREAD_OWNER_FOR_DEBUG
int threadOwner;
#endif
};
// Caller.cc in code base B
#include "xxx/xxx/Lock.h"
Lock lockObject;
lockObject.Lock();
In code base A, we by default will enable TRACK_THREAD_OWNER_FOR_DEBUG and may change it just before final release day.
We hit some hard bug because TRACK_THREAD_OWNER_FOR_DEBUG are different in A and B, and cause memory corruption because the sizeof(Lock) is different in two library.
So how to protect from this error? Can we trigger an compiler error when build the caller.cc file if the build macro TRACK_THREAD_OWNER_FOR_DEBUG is different in two project?
It is not possible to make this into compiler error, however it should be possible to make this into reasonably clear linker error by exporting some symbol which name depends on the currently defined macros. For example using static guard variable:
// Foo.hpp - library header file
#pragma once
class Foo
{
public: Foo();
#ifdef IMPORTANT_CONDITION
int m_field;
#endif
};
class ConditionGuard
{
public:
ConditionGuard(void) noexcept
{
#ifdef IMPORTANT_CONDITION
CONDITION_ON();
#else
CONDITION_OFF();
#endif
}
#ifdef IMPORTANT_CONDITION
private: static void CONDITION_ON(void);
#else
private: static void CONDITION_OFF(void);
#endif
};
static ConditionGuard const condition_guard{};
// Foo.cpp - library implementation file
#include "Foo.hpp"
Foo::Foo(void) {}
#ifdef IMPORTANT_CONDITION
void ConditionGuard::CONDITION_ON(void) {}
#else
void ConditionGuard::CONDITION_OFF(void) {}
#endif
Now when user code includes library header Foo.hpp it will also trigger construction of condition_guard static variable which will call a library function depending on condition being protected. So if there is a translation unit including Foo.hpp where IMPORTANT_CONDITION is defined differently than in compiled library then there will be a linker error for missing CONDITION_ON or CONDITION_OFF. CONDITION_ON and CONDITION_OFF function names should contain error text.
One option is to just include the full code for A into project B. What are you trying to do by compiling A into a static library?
I think you're best option is to generate different .a files depending the target. i.e. libA_debug.a when TRACK_THREAD_OWNER_FOR_DEBUG is set, libA.a when it is not.
Then you could set the library to link B to based on whether you are compiling a debug or release version.
I have two classes
RequestManager.h
#ifndef REQUESTMANAGER_H
#define REQUESTMANAGER_H
#include "RequestClient.h"
class RequestManager
{
public:
void AddReqeustItem(RequestClient *req);
private:
std::list<RequestClient*> m_reqClientContainer;
};
#endif
RequestClient.h
#ifndef REQUESTCLIENT_H
#define REQUESTCLIENT_H
class RequestManager; // Forward declaration to avoid cyclic inclusion.
class RequestClient {
public:
void CreateRequest(RequestManager* pManager)
{
// ... I am creating a request.
pManager->AddReqeustItem(req);
};
#endif
In the code above I am getting error undefined RequestManager in Request client class. What is the problem and how can I solve it?
You cannot use a type with only a forward declaration. Forward declaration are used to say to compiler that type exists but compiler does not know the content of the type.
My advice:
In header file, I would only define class and function members. So forward declaration is possible if only pointer are used.
In body file, write the code your member function and include the header files
put the member function definition in a source file which #includes both headers.
Or, if you still want it to be inline (or if it's templated), then put the definition of the member function body further in the header, after all relevant code is defined. In the case of a single header file (which does make sense here):
class B; // forward decl
class A {
void use(B*);
};
class B {
void use(A*);
};
void A::use(B*b) { /* ... */ }
void B::use(A*a) { /* ... */ }
Note the splitting of the code into files (several headers and one source) is only a convenience for the programmer (making it much simpler to maintain and use by other parts of the code), but from the point of view of the compiler this doesn't matter: it sees only one big file of code (after pre-processing). So, it's up to you how you split the above layout into headers and source file.
You use the method RequestManager::AddReqeustItem(), but there's only a forward declaration of RequestManager. With just a forward declaration the compiler doesn't even know which methods of RequestManager exist. So, to fix this problem, you must provide the definition of RequestManager, which is usually in the header file.
Move the method definition of CreateRequest() into the cpp file and include RequestManager.h there
RequestManager.cpp:
#include "RequestManager.h"
...
void CreateRequest(RequestManager* pManager)
{
// ... I am creating a request.
pManger->AddReqeustItem( req);
}
After creating and definition class (in "h file").
How do I decide to create (or not) "cpp file" (only for the class) in addition to "h file" (that belonging to the class)?
Here is a small example to get you going.
this is Foo's header file. let's call it "foo.h"
#pragma once
#ifndef FOO_H
#define FOO_H
class Foo{
public:
void function();
protected:
private:
};
#endif
This is Foo's source file. Let's call it "foo.cpp"
#include "foo.h"
void Foo::function(){
// ... implement ...
return;
}
compiling them together, we can create an object file. We'll call it "foo.o"
You can use your class in a program provided that you link "foo.o".
Example:
#include "foo.h"
int main(){
Foo foo;
foo.function();
return 0;
}
An h file is a descriptor file, that describes the signature of your functions/classes, so that other classes in other cpp files may use it.
You need to think of an h file as a contract. You are declaring an obligation.
Later on, when you decide to implement the cpp, you are fulfilling the obligation.
Other classes/cpp files can rely on your obligation alone, assuming that you will also implement the obligation in a cpp.
For example:
You create an .h file "myClassA.h" and declare a class called myClassA with a member method called myClassA.SayHello()
You include myClassA.h in another class you create myClassB.cpp, that way myClassB knows that myClassA has a method called SayHello() and it can call it.
If you do not include myClassA.h and you try to call myClassA.SayHello() inside myClassB.cpp, you'll get an error from your compiler, as myClassB does not "know" of myClassA.
If you do include the h file but did not bother to actually create and implement myClassA in myClassA.cpp, you will get a compilation error, since no implementation was found.
The best practice is to separate the header and implementation files so you define the class inside the header file .h and implement it inside the .cpp file, this will help you to trace and debugging the errors and shows a clean code ,
Just note in the templates classes it have to be defined in a separate header file to keep your code structured well and clean by separating templates from normal classes
If I have a pure virtual class like the following:
I have class structure like the following:
class interface_class {
virtual void someFunction(MyClassA& a) = 0;
virtual void someFunction(MyClassB& b) = 0;
}
What is the correct way to include MyClassA/MyClassB? Should I do some forward declaration in the header file of the interface class and do the real inclusion in the header file of the implemention, or should I include the header file of MyClassA/B directly in the interface class?
Use Forward Declarations for both the classes.
In fact always use forward declarations wherever you can.
Using forward declarations saves you compilation time & also restricts you from creating unneeded dependencies.
You should use a forward declaration in a separate header file.
That is you have your current header files with the definition of MyClassA and MyClassB. You'll need to group classes used at the same time and create a new header file like this:
file MyClassesFwd.h (naming convention up to you)
namespace XX {
class MyClassA;
class MyClassB;
}
Your interface header:
#include <MyClassesFwd.h>
// ... your interface definition ...
An actual source file will look like this on the other hand:
#include <MyClassA.h>
#include <MyClassB.h>
#include <MyInterface.h>
This will prevent you from rewriting the forward declaration everytime.