I came across an implementation which had the pimpl class as a header and included that in the pimpl implementation. Does it even make sense? Something like this:
UI.h
class UI {
public:
UI();
virtual ~UI();
// bunch of methods
private:
UIImpl* m_impl;
}
UIImpl.h
class UIImpl
{
public:
UIImpl( ...) ;
......
}
UIImpl.cpp
#include "UIImpl.h"
UIImpl::UIImpl()
{
//Actual Implementation
...
}
I was thinking that the reason for PIMPL was to hide the implementation totally inside the cpp file. Does having a header defeat the purpose?
They're different kinds of header. UI.h is "public" - it's part of the external interface of the library, for use by its clients.
UIImpl.h is "private," just as the UIImpl.cpp is. As long as it's never included in a public header, it can remain invisible to clients, just as the .cpp itself can.
There can be several reasons for splitting the impl class definition into a header file. Perhaps some other implementation classes are passed UIImpl& parameters. Perhaps it's easier to run doxygen on headers only. Perhaps it's just project policy.
The bottom line is, it's still Pimpl, as long as you don't publish the private header.
I was thinking that the reason for PIMPL was to hide the implementation totally inside the cpp file. Does having a header defeat the purpose?
Not necessarily. pIMPL can be used for fast value swapping (probably in architectures before C++11/move semantics), bridge design pattern or any other number of other reasons.
An example of bridge design pattern:
class WinImpl { virtual ~WinImpl() = 0; /* other interfaces here */ };
// different header file(s)
#ifdef WIN32
class WindowsWinImpl: public WinImpl { /* ... */ };
#else
class LinuxWinImpl: public WinImpl { /* ... */ };
#endif
// different header file
class Window { private: WinImpl* pImpl /*= OSWindowFactory::CreateImpl();*/ };
In this case you have a pImpl model, where it is perfectly OK to include the definition of WinImpl in the header of Window class (because the purpose is not to hide the implementation but to abstract it's interface).
It makes perfect sense to do this. It allows the UIImpl.h (and related .cpp) to be modified, without having to change code that is dependent on UI.h. Since the UIimpl class is just stored as a pointer [and presumably the UI itself only has access to public methods of the UIimpl class, nothing about the UIimpl class is known to the UI.h code.
In fact, you probably NEED the "UIimpl.h" to allow the public functionality of the class to be seen by the UI class.
E.g.
class UIImpl
{
public:
UIImpl( ...) ;
void func() { ... }
}
class UI
{
public:
UI();
virtual ~UI();
// bunch of methods
void func() { m_impl->func(); }
...
}
For this to work, UI needs to know the public interface provided by the UIimpl class.
Yes, it does make sense.
An example of use: in code developed for more than one operating system, UI.h would be visible from the operating-system-independent code, but not UIImpl.h. The operating-system-dependent-code (implementation code) would see both headers, UI.h and UIImpl.h
Related
I'm using the pimpl idiom heavily in my code, mostly to reduce compilation time.
I have a situation where I'm calling into a C library. I have a C++ wrapper class which has its interface, and the gory details are all in the impl, of course:
class some_class {
public:
void some_init();
...
private:
class impl;
std::unique_ptr<impl> m_pimpl;
}
In the cpp file I have to register a callback with the C library where I get to give it a pointer. I want to forward this function call to the corresponding member function. The client (i.e. the user of this function) doesn't have to know about this detail at all:
static void from_c_func(void *ptr_to_class_impl) {
static_cast<some_class::impl *>(ptr_to_class_impl)->from_c_func();
}
void some_class::some_init() {
create_c_thing(static_cast<void *>(this->m_pimpl.get()), from_c_func);
}
The problem is that some_class::impl is declared private. I can only think of imperfect solutions:
Make the class impl; public in the header file. This is not ideal because it really should be private - it just happens to be an implementation detail that a non-class function needs to see it.
Put from_c_func in the header file and friend it. This is not ideal because the implementation details of some_class are leaking out. Changing the implementation may require changing the header file, which would then recompile a lot of things which don't need recompilation, which would make me unhappy.
Give from_c_func a pointer to some_class itself, and then call a function on some_class. This would require putting that function in the header file, which is again, an implementation detail - and it would have to be public anyway for the non-friend function to call it.
What to do? My best bet so far seems to be #1, but is there any better way?
You may move your function in impl
static void some_class::impl::from_c_func(void *ptr_to_class_impl) {
static_cast<some_class::impl *>(ptr_to_class_impl)->from_c_func();
}
I have always thought of header files as a sort of 'public interface' describing a class, in which case it would be better to keep private fields and functions in the .cpp file.
I understand that private fields need to be in the header so that other classes can tell how much memory an instance of a class will consume, but it occurred to me as I was about to write a private helper function, that this function could be made static, in which case there was no need for it to be 'part of the class' at all, it could just as easily be a regular function in the class definition's .cpp file.
It then occurred to me that all private functions could potentially be rewritten to be static by accepting pointers/references to class fields instead of expecting to be defined in the class.
This would eliminate the need to declare any private functions in the header file.
I do like to follow conventions, so is it considered an established convention in C++, that non-static private functions should be in the header file? What about static functions or static constants?
I'm going to put in some code to explain what I'm getting at:
.h file:
#ifndef SOME_CLASS_H
#define SOME_CLASS_H
class SomeClass
{
private:
int x;
public:
void combineWithX(int y);
};
#endif
.cpp file
#include "SomeClass.h"
void someHelper(int* x)
{
*x = (*x) + 1;
}
void SomeClass::combineWithX(int y)
{
someHelper(&x);
x += y;
}
Note that someHelper(int* x) in the .cpp file references the private member x in spirit, but not directly, and therefore does not need to appear in the header. I'm wondering if this sort of thing is considered 'bad style'.
Private helper functions can be hidden from the public header file by moving them to an inner class. This works because the inner class is considered part of the class and can access the surrounding class's private members.
Unlike the PIMPL idiom, this does not have any dynamic allocation or indirection penalty. Compile times should be faster when editing/refactoring private functions, as there isn't any need to recompile all the files, including the public header.
Example:
public .h file
#ifndef SOME_CLASS_H
#define SOME_CLASS_H
class SomeClass
{
private:
// Just forward declaring in public header.
struct Private;
int x;
public:
void combineWithX(int y);
};
#endif
in .cpp file
#include "SomeClass.h"
// Declare all private member functions of SomeClass here
struct SomeClass::Private
{
static void someHelper(SomeClass& self)
{
self.x = self.x + 1;
}
};
void SomeClass::combineWithX(int y)
{
Private::someHelper(*this);
x += y;
}
I agree that it is a problem that implementation details need to be exposed in a header file; it interferes with separation of interface and implementation.
Moving private helper functions to be free functions in the .cpp file (I presume that is what you meant by "static") won't work if those functions need to access private member variables.
You may be interested to look at the pImpl idiom (more)
Sometimes I see people using two different headers, a public header and a private one, like this:
// SomeClass.h - - - -
SomeClass
{
public:
// public functions
}
// SomeClass_.h - - - -
SomeClass
{
public:
// public functions
private:
// private functions
}
// SomeClass.cpp - - - -
#include "SomeClass_.h"
// SomeClass implementation
This has the advantage of a public header that isn't cluttered with private function declarations, but it requires the developer to maintain 3 copies of each function signature.
Header files have long been recognized by many as being problematic in general, not only because of the added maintenance overhead associated with them, but also because of the effect they have on the build environment. It's easy to write code or set build settings that cause a cascade of system or external headers to fail to compile, resulting in a large number of potentially obscure errors. C++20 Modules are an alternative that may be worth exploring.
I wish to compile part of my code as a static library to include in other project. Of course I'll have to distribute the compiled library and an header file containing the class declaration and the public members, but I don't know if it's possible to move all private members and declarations to a place different than the header file.
Example:
In the project.h file:
class MyClass
{
public:
MyClass();
void Give_me_an_input(int);
int Get_your_output();
private:
int a, b;
int MySecretAlgorithm();
};
In the .cpp file:
MyClass::MyClass()
{
a = 1;
b = 0;
}
void MyClass::Give_me_an_input(int c)
{
b = c;
}
int MyClass::Get_your_output()
{
return MySecretAlgorithm();
}
int MyClass::MySecretAlgorithm()
{
return (a + b);
}
Is there a way to move all private members int a, b; and int MySecretAlgorithm(); to a place different than the header file?
The pointer to implementation idiom can be used in such a scenario, commonly referred to as pimpl.
The basic idea is to take the implementation details out of the declaration
and simply have an opaque pointer to the implementation details.
std::unique_ptr is used in the the following example; but you could of course just use normal pointers.
// my_class declaration unit.
class my_class {
private:
class impl;
unique_ptr<impl> pimpl;
public:
};
// my_class implementation unit
class my_class::impl {
int whatever;
int whenever;
};
my_class::my_class(): pimpl( new impl )
{
}
Over the years I've seen some hacks to do this, but I don't think they are worth it. If your library is reasonably 'chunky' (ie: no method is being called a billion times a microsecond); and you can re-write chunks of your code...
You might consider making all the public stuff an abstract class (all virtual = 0) and then deriving your concrete classes from it.
Down sides of this:
- All your public calls become virtual (some optimizations can bypass this, but not often).
- You can't 'new up' your classes anymore, you'll need to implement a factory pattern.
The problem with any of the other hacks I'm familiar with is that they basically declare the methods in one set of headers, and then redeclare the same things with the 'real' implementation in private headers - depending on the linker to match up the names. A couple problems here are:
Maintaining this mess sucks. You can't use an #ifdef because it sounds like you want to physically hide your implementation. So you have dual maintaining, or a build step that generates your public headers.
Can only be used via pointer. You have to play games making constructors private and still have a factory because the compiler won't generate structs of the right size if you let the client gen it by value (or even with new).
Finally, I once saw a hack where the programmer tried to declare a byte array in the private area of the 'public' class so that the client code could still declare by value or 'new' it themselves. This suffers all the previous problems, plus you probably don't want to have to 'know' the size of the structs since they depend on packing and alignment. Your 'build step' would more or less have to have a runtime component that used sizeof() - and now you have a versioning problem if you want to change the size of the struct/class.
I am writing up a simple C++ program whose interface and implementation are separated.
Both of them contains only one class.
Is it OK if the I keep the name of the interface and implementation the same, while using a different name of that class within?
As far as the C++ language and compiler are concerned, you can name your classes anything you like; class names do not need to be in any way related to the names of the files that contain their interface or their implementation. It's even perfectly legal to have multiple classes declared together in a single .h or .cxx file.
From a style perspective, other programmers might find it easier to understand your source code if you keep your class names matching your file names, but it's really up to you whether you want to do that or not.
Yes it is OK to do what you described. For instance, the below can be used when you want to hide the interface implementation details.
// foo.h
class Foo
{
public virtual void bar() = 0;
};
// foo.cpp
class FooImpl : public Foo
{
public:
void bar()
{
// do something
}
};
// factory
Foo* Foo::Create()
{
return new FooImpl();
}
I want to make two classes: an object and an object_manager, but I'm confused about how they should see/include each other. I've heard that it's forbidden for two headers to include each other and if my code dependencies has circles then it's a bad code design and usually it should be like a hierarchy structure (town->house->furniture and furniture shouldn't know about town existence).
But here I have the object_manager which knows and holds all the objects, and the objects should have an option to create new objects, but then they should call the object_manager which will force them to know about it existence and this will create a circle in the structure, which is bad.
It's like one process wants to create a new process by calling the OS system calls, so the OS and the process knows about each other.
Is there a way I can implement this in the right code design, or should it just be bad sometimes?
I thought maybe the objects should have a special place where they will store all their "system calls", and the object_manager will check it from time to time, but maybe there is a better way.
Use forward declaration:
class ObjectManager;
class Object
{
private:
ObjectManager* m_objManager;
....
public:
....
};
In .cpp file you can include the ObjectManager.h
Also instead of ObjectManager make the interface which will give you more abstraction for implementation IObjectManager.
Actually it is possible to implement the two. And no it's not really bad. Here is some partial code.
let's say you have a header file
myobject.h
#ifndef _MYOBJECT
#define _MYOBJECT
// Declare the Object Manager class in it.
class MyObjectManager; // forward declaration
class MyObject {
MyObjectManager manager;
registerSelf(MyObjectManager &m);
}
#endif _MYOBJECT
Now for the ObjectManager header
#ifndef _MYOBJECT_MANAGER
#define _MYOBJECT_MANAGER
class MyObject; // forward declaration
class MyObjectManager {
private:
List list[];
public:
registerObject(MyObject &o);
};
#endif
Implementation of objectmanager
#include <myobject>
#include <myobjectmanager>
MyObjectManager::manageMyObject(MyObject &o) {
list += o; /* etc. */
}
Implementation of object
#include <myobject>
#include <myobjectmanager>
MyObject::registerSelf(MyObjectManager &manager) {
this.manager = manager;
manager.registerObject(*this);
}
There are many cases where classes need to know about each other. The only issue with this is they have to know about each other partially or at least one class does. The way the issue is generally solved is using forward declarations . The only sticky issue is in class A you can't declare a member that has a type of class B only a pointer or a reference to Class B.
class B;
class A
{
B* oB;
};
class B
{
A oA;
}:
Some general recommendations to remove the coupling between headers follow:
Forward Declare what you can. Sometimes your A class uses others classes (X,Y,..) only by passing references or pointers. So in your A.h you can declare methods that use these X,Y return or argument types without the compiler needing to know the complete type. That means that A.h does not need to include X.h or Y.h
Use PImpl idioms, Sometimes the best way to decouple implementation from interface (without using virtual or abstract classes) is doing something like:
Foo.h
class Foo {
struct Impl;
Impl* m_impl;
public:
Foo();
void SomeMethod();
}
Foo.cpp
#include "X.h"
struct Foo::Impl {
/* actual implementation */
...};
Foo::Foo() : m_impl( new Foo::Impl() ) {};
void Foo::SomeMethod() {
m_impl->SomeMethod();
}
What you're describing is an object that can only exist inside another object.
A good way to implement this is with nested classes:
class object_manager {
public:
class object { // object_manager::object. public allows it to be used outside of manager
public:
void foo() {
object* t = construct(); // can call object_manager methods
}
};
private:
object my_objects[5]; // can create objects
static object* construct() { return NULL; }
};
Keep in mind that you can still have 2 cpp files for object and object_manager.
The CPP files can include each other's headers without causing a compile problem (whether it's correct from a design point of view is a different matter, but should be ok in yur case). This means they can call each other's methods, etc.
Regarding the header files, the "object manager" header will most likely include the "object" header because the "object manager" class needs to work with "object" class instances. If the "object" header file needs to know about the "object manager" class, place a forward declaration for the "object manager" in the "object" header file. That way you can use pointers and references to the "object manager" in the "object" header file without creating a circular include dependency.