Consider this header file:
#ifndef __FOLDER_H__
#define __FOLDER_H__
#include <boost/filesystem.hpp>
class Folder
{
public:
Folder(char* arg);
private:
std::vector<boost::filesystem::path> files;
};
#endif
Everybody including Folder.h will also include boost/filesystem.hpp. However, there are no boost/filesystem types in the public interface of Folder. boost/filesystem.hpp kind of leaks out of Folder.h for the technical reason of declaring a private variable.
I would like to avoid this. Would it be best to declare private variables in the implementation file Folder.cc? Is there some syntax to declare a block of private variables in the implementation file?
There are quite a few idioms to hide the implementation details of a given class. Two of the ones I tend to use are PIMPL and interfaces.
PIMPL
PIMPL is a paradigm where you define a private structure with no definition in the header file, and all of your private implementation details are stored in this private structure. You then reference that structure with a pointer to the implementation, traditionally called pImpl (hence the name).
With the PIMPL idiom, Folder.h becomes this:
//this replaces the include guards and is available in almost all modern compilers.
#pragma once
class Folder
{
public:
Folder(char* arg);
private:
struct FolderImpl* pImpl;
};
And in Folder.cc, you can define FolderImpl as follows:
#include <vector>
#include <boost/filesystem.hpp>
struct FolderImpl
{
std::vector<boost::filesystem::path> files;
}
From there, any operations that work with the files member reference it by pImpl->files.
Interfaces
Interfaces are actually something I "stole" from Microsoft COM. The basic idea is you declare an abstract class, one without any member variables, and inherit from this class in a private header file compiled into your library.
In the Interface idiom, Folder.h becomes this:
class Folder
{
public:
virtual bool DoesFileExist(char* file) = 0;
virtual File* OpenFile(char* file) = 0;
...
static Folder* Create(char* arg);
};
Folder.cc looks like this:
#include "Folder.h"
#include "FolderImpl.h"
Folder* Folder::Create(char* arg)
{
return new FolderImpl(arg);
}
And FolderImpl.h is:
#include "Folder.h"
#include <vector>
#include <boost/filesystem.hpp>
class FolderImpl : public Folder
{
public:
FolderImpl(char* arg);
bool DoesFileExist(char* file) override;
File* OpenFile(char* file) override;
...
private:
std::vector<boost::filesystem::path> files;
};
At the cost of one level of indirection, you could consider doing something like this:
#ifndef FOLDER_H
#define FOLDER_H
#include <memory>
struct FolderPrivateVars;
class Folder
{
public:
Folder(char* arg);
private:
std::unique_ptr <FolderPrivateVars> private_vars;
};
#endif
And then in folder.cc
#include <boost/filesystem.hpp>
struct FolderPrivateVars
{
std::vector<boost::filesystem::path> files;
};
Folder::Folder(char* arg) : private_vars (std::make_unique <FolderPrivateVars> ())
{
...
}
Note that this approach hides all of Folders private variables from prying eyes, which would (for example) mean that modules using it would not need to be recompiled if these change. It might, however, have implications if you want to inherit from Folder.
Related
I have currently implemented a library using the pImpl idiom as such (just an example);
// library.h
class lib_public_type
{
class impl;
std::unique_ptr<impl> impl__;
public:
void libTypeFunction();
}
// library.cpp
#include "library.h"
class lib_public_type::impl
{
private:
std::string libVar1;
void libPrivateFunction1()
{
...
}
void libPrivateFunction2()
{
...
}
}
lib_public_type::libTypeFunction()
{
libPrivateFunction1();
libPrivateFunction2();
}
Now I would like to remove as much unneeded information from the header file as possible for another project using a built version of the library. I was wondering if there is a better way of removing the internals from the header of lib_public_type without resorting to maintaining two separate headers?
Would it be possible to do something like;
// library.h
#ifndef PROVIDES_IMPL
// define as empty string if not already defined
#define PROVIDES_IMPL
#endif
class lib_public_type
{
PROVIDES_IMPL
public:
void libTypeFunction();
}
// library.cpp
#define PROVIDES_IMPL class impl;\
std::unique_ptr<impl> impl__;
#include "library.h"
...
Or would this have unwanted consequences for the project using the library?
EG,
//this is myclass.h
class myclass
{
public:
int publicfunction();
private:
int myprivatefunction();
};
//myclass.cpp
#include "myclass.h"
int myclass::publicfunction()
{myprivatefunction();
blabla...}
int myclass::privatefunction()
{blabla...}
So, for users can access the class,we will provide the header file to the users. But shouldn't we conceal the internal implement details of the class??? I mean, when the users get myclass.h, they will find that the class contains a private function myprivatefunction
You can export the private members inside a struct
//this is myclass.h
class myclass{
private:
struct myClassPrivateMembers;
myClassPrivateMembers* privParts;
public:
// ...
};
And in the *.cpp file:
//this is myclass.cpp
struct *myClassPrivateMembers{
int myprivatefunction();
}
myclass::myclass(){
privParts = new myClassPrivateMembers;
};
That way the user won't be able to see things you hidden inside myClassPrivateMembers, because they'll be inside the *.cpp file, not declared in the header file.
This is widelly known as the "pimpl" idiom.
Your header file isn't just your public interface. It's a description of your data layout for the compiler. It is perfectly normal that the private members get shown in the header file. private is not a security mechanism and never will be.
It's a bit strange, but it falls out from a simple yet efficient way of going about the problem.
You might as well separate your interface and your implementation.
myinterface.h
class myinterface
{
public:
virtual int publicfunction() = 0;
};
myclass.h
class myclass : public myinterface
{
public:
virtual int publicfunction();
private:
int privatefunction();
};
myclass.cpp
#include "myclass.h"
int myclass::publicfunction()
{myprivatefunction();
blabla...}
int myclass::privatefunction()
{blabla...}
You don't have to expose myclass.{h,cpp} to library users.
But this might be an overkill... (I would call this "Java folks' way")
I'm attempting to build a library that uses a third-party library internally, but I do not want to expose and of this third-party library to the user of my library. This way, when the static library is built, the user will only need my header and the compiled library.
How do I deal with private members in my class definitions that are defined in the 3rd party library?
For example . .
header:
#include "ThirdPartyLib.h"
class DummyClass
{
TypeFromThirdParty tftp;
public:
bool checkStuff(const float) const;
};
implementation:
#include "ThirdPartyLib.h"
#include "dummy.h"
bool DummyClass::checkStuff(const float t)
{
return tftp.isOk(t);
}
The offending portion is the #include "ThirdPartyLib.h" in the header, as then the user of my library will need more than my library.
One way of getting around this might be to forward declare all third party types used in the header and then replace the value types with references, but I'm wondering if there is another method or design that I am completely overlooking?
The "private implementation class" or "pimpl" idiom is one approach. This keeps all mention of the third-party library (and other implementation details) out of the header, at the cost of an extra level of indirection:
// header
#include <memory>
class DummyClass {
public:
DummyClass();
~DummyClass();
bool checkStuff(float t);
private:
struct Impl;
std::unique_ptr<Impl> impl;
};
// source
#include "DummyClass.h"
#include "ThirdPartyLib.h"
struct DummyClass::Impl {
TypeFromThirdParty tftp;
};
DummyClass::DummyClass() : impl(new Impl) {}
// This must be defined here, since ~unique_ptr requires Impl to be complete
DummyClass::~DummyClass() {}
bool DummyClass::checkStuff(float t) {return impl->tftp.isOk(t);}
Another approach is to define an abstract interface, and a factory to create the concrete implementation class. Again, this removes all implementation details from the header, at the cost of an extra indirection:
// header
#include <memory>
struct DummyInterface {
virtual ~DummyInterface() {}
virtual bool checkStuff(float t) = 0;
static std::unique_ptr<DummyInterface> create();
};
// source
#include "DummyClass.h"
#include "ThirdPartyLib.h"
struct DummyClass : DummyInterface {
TypeFromThirdParty tftp;
bool checkStuff(float t) {return tftp.isOk(t);}
};
std::unique_ptr<DummyInterface> DummyInterface::create() {
return std::unique_ptr<DummyInterface>(new DummyClass);
}
I'm starting to learn C++ (coming from Java), so bear with me.
I can't seem to get my method declaration to accept a class I've made.
'Context' has not been declared
I think I'm not understanding a fundamental concept, but I don't know what.
Expression.h
#include "Context.h"
class Expression {
public:
void interpret(Context *); // This line has the error
Expression();
virtual ~Expression();
};
Context.h
#include <stack>
#include <vector>
#include "Expression.h"
class Context {
private:
std::stack<Expression*,std::vector<Expression*> > theStack;
public:
Context();
virtual ~Context();
};
You have to forward declare Expression in Context or vice versa (or both), otherwise you have a cyclic dependency. For example,
Expression.h:
class Context; // no include, we only have Context*.
class Expression {
public:
void interpret(Context *); // This line has the error
Expression();
virtual ~Expression();
};
Context.h:
#include <stack>
#include <vector>
class Expression; // No include, we only have Expression*
class Context {
private:
std::stack<Expression*,std::vector<Expression*> > theStack;
public:
Context();
virtual ~Context();
};
You can perform the forward declarations because the full definition of the classes isn't needed, since you are only referring to pointers to the other class in each case. It is likely that you will need the includes in the implementation files (that is, #include "Context.h" in Expression.cpp and #include Expression.h in Context.cpp).
Finally, remember to put include guards in your header files.
In C++, class definitions always have to end with a semi-colon ;
so example:
class foo {};
Java and C# doesn't require that, so I can see your confusion.
Also it looks like both your header files include each other. Thus it's kind of like a snake eating it's tail: Where does it start? Thus in your Expression.h you can replace the 'include' with a forward declaration instead:
class Context;
class Expression {
public:
void interpret(Context *); // This line has the error
Expression();
virtual ~Expression();
}
And last but not least, you should put a compiler guard to prevent the header from getting included more than once into a .cpp file. You can put a #pragma once in the top of the header file. That is useful if you are using visual studio and the microsoft compiler. I don't know if GCC supports it or not. Or you can wrap your header file like this:
#ifndef EXPRESSION_H_
#define EXPRESSION_H_
class Context;
class Expression {
public:
void interpret(Context *); // This line has the error
Expression();
virtual ~Expression();
}
#endif
you might need to forward declare the classes Context and Expression in the header files before the #include
e.g.
#include <stack>
#include <vector>
// forward declaration
class Context;
class Expression;
#include "Expression.h"
class Context {
private:
std::stack<Expression*,std::vector<Expression*> > theStack;
public:
Context();
virtual ~Context();
}
If I'm creating a static library with a header file such as this:
// Myfile.h
#include "SomeHeaderFile.h" // External library
Class MyClass
{
// My code
};
Within my own project I can tell the compiler (in my case, Visual Studio) where to look for SomeHeaderFile.h. However, I don't want my users to be concerned with this - they should be able to include my header without having to inform their compiler about the location of SomeHeaderFile.h.
How is this type of situation normally handled?
This is a classic "compilation firewall" scenario. There are two simple solutions to do:
Forward-declare any classes or functions that you need from the external library. And then include the external library's header file only within your cpp file (when you actually need to use the classes or functions that you forward-declared in your header).
Use the PImpl idiom (or Cheshire Cat) where you forward-declare an "implementation" class that you declare and define only privately (in the cpp file). You use that private class to put all the external-library-dependent code to avoid having any traces of it in your public class (the one declared in your header file).
Here is an example using the first option:
#ifndef MY_LIB_MY_HEADER_H
#define MY_LIB_MY_HEADER_H
class some_external_class; // forward-declare external dependency.
class my_class {
public:
// ...
void someFunction(some_external_class& aRef); // declare members using the forward-declared incomplete type.
};
#endif
// in the cpp file:
#include "my_header.h"
#include "some_external_header.h"
void my_class::someFunction(some_external_class& aRef) {
// here, you can use all that you want from some_external_class.
};
Here is an example of option 2:
#ifndef MY_LIB_MY_HEADER_H
#define MY_LIB_MY_HEADER_H
class my_class_impl; // forward-declare private "implementation" class.
class my_class {
private:
std::unique_ptr<my_class_impl> pimpl; // a vanishing facade...
public:
// ...
};
#endif
// in the cpp file:
#include "my_header.h"
#include "some_external_header.h"
class my_class_impl {
private:
some_external_class obj;
// ...
public:
// some functions ...
};
my_class::my_class() : pimpl(new my_class_impl()) { };
Say the external header file contains the following:
external.h
class foo
{
public:
foo();
};
And in your library you use foo:
myheader.h:
#include "external.h"
class bar
{
...
private:
foo* _x;
};
To get your code to compile, all you have to do is to forward declare the foo class (after that you can remove the include):
class foo;
class bar
{
...
private:
foo* _x;
};
You would then have to include external.h in your source file.