I am new at building distributable libraries written in C++ and I am getting a bit lost.
I have created a .cpp file with wrappers for all functions I want the library to offer users, and I have written 2 .h files, one public and one private. Below is a dummy example of my header files:
public.h:
class myclass
{
public:
public_function();
private:
}
private.h:
class myclass
{
public:
public_function();
private:
anotherClass instanceofClass;
}
Note that the implementation of public_function() uses the "instanceofClass" in the code.
I have been able to compile with no problem the code using the private class and to compile and link the library with external programs using the public header and the compiled library. When executing that code, though, I am getting segmentation faults that I suspect have to do with lack of proper initialization of "instanceofClass".
Am I doing the right thing? Am I forced to instantiate "instanceofClass" inside the implementation of public_function() for it to be initialized properly, or is there anything else I should do instead?
Thanks a lot.
You can't declare the same class 'myclass' in two different ways. There has to be a single class definition. If you want to hide the implementation's API you want to use the 'Pimpl' idiom. So your public class has a single pointer to a private class. For example:
public.h
class myclass_private;
class myclass {
private:
myclass_private* pimpl;
public:
myclass();
void public_function();
};
public.cpp
myclass::myclass() {
pimpl = new myclass_private;
}
void myclass::public_function() {
pimpl->private_function();
}
private.h
class myclass_private {
public:
void private_function();
};
The myclass defined in public.h has no members, and is therefore sized 1 byte. The myclass defined in private.h encapsulates anotherClass, and is therefore whatever size anotherClass is. This inconsistency is the root of your problem.
What you ought to do is have only one header, and use a pointer (which doesn't require a class definition) to enable hiding the implementation of anotherClass. I'll repeat Joachim's link to the pimpl idiom for elaboration.
The definition of a class shall not changr between different translation units. This is one of the aspects of the One Definition Rule. What you might want to donis to define the publicly visible class to have a pointer to a private implementation: the Pimpl Idiom:
class Public {
public:
...
private:
struct Impl;
Impl* impl_;
};
The struct Impl would only be defined in the implementation file.
Your class lacks a proper constructor, which means that the compiler will provide a default one based on the content of the class definition. If that definition isn't consistent accross all the code, it won't get initialized the same way everywhere, and some data may be missing.
If you want to hide the implementation details of instanceofClass, just do a forward declaration in the header (the private header you're providing is correct, you can use it as your public one), and provide an implementation somewhere in your code.
Related
I want to use an abstract base class for the purpose of interfacing and usability. This abstract base class will be used as the parent class for several different derived classes, each of which has need of a certain subset of the pure virtual functions in the abstract base class. An outline of my scheme is as follows.
abstractclass.hpp
AbstractClass{
/* Declaration */
void pureVirt1() = 0;
void pureVirt2() = 0;
void pureVirt3() = 0;
};
derivedclass1.hpp
DerivedClass1{
/* Declaration */
void pureVirt1();
};
derivedclass2.hpp
DerivedClass2{
/* Declaration */
void pureVirt2();
};
derivedclass3.hpp
DerivedClass3{
/* Declaration */
void pureVirt3();
};
Given the current implementation, all of the above classes are abstract classes and no objects can be created from these classes. In the past, I have resolved this issue with preprocesser directives around each virtual function.
abstractclass.hpp
AbstractClass{
#ifdef _1
void purVirt1()=0;
#endif
...
And at the top of each derived class's header file, before the include to abstractclass.hpp I would write something like the following
derivedclass1.hpp
#define _1
#include"abstractclass.hpp"
...
This worked when I was working with small projects and not writing make files. The header for the abstract class was effectively altered based on which derived class was using it, so long as I kept my directives in the correct place. Now that I am using makefiles, this does not work. abstractcalss.cpp is compiled without any of the virtual functions in the header file because it is compiled separately from the derivedclass. I am looking for a good workaround for this.
I want this functionality because I have many similar derived classes from this abstract base class that are used by a variety of other tools I have written. I want to keep these other tools as simple as possible and just use pointers to the abstract class instead of writing template classes for everything.
--Further information
I have a situation where AbstractClass is in a has-a relationship with SubAbstractClass and is implemented by use of having a pointer to SubAbstractClass in AbstractClass. Furthermore, for each of the derived classes there is a similar has-a relationship with SubDerivedClass1, SubDerivedClass2, … I don’t want to write containers for every new class that I create, especially because I can combine my derived classes to create novel classes that are important and functional and any such combination of new classes would require creating the appropriate set of subclasses. To this end, it is useful to have an ABC to allow the pointers to be declared once and work for any derived class.
[...] several different derived classes, each of which has need of a
certain subset of the pure virtual functions in the abstract base
class.
Obviously, this won't work. Moreover, your attempts to make things simpler are, in my opinion, having the opposite effect. You are making things much more complex by introducing preprocessor black magic to comment-in and comment-out specific parts of the interfaces.
You're swimming upstream without a paddle here. Instead of having one interface class to which you add and remove methods piecemeal, just develop several different interface classes that do a better job of modularizing the functionality:
AbstractClass1{
/* Declaration */
void pureVirt1() = 0;
};
AbstractClass2{
/* Declaration */
void pureVirt2() = 0;
};
AbstractClass3{
/* Declaration */
void pureVirt3() = 0;
};
Trying to make one universal, God class that you blow pieces off of to suit specific modules's needs is going to eventually bite you, and hard. Consider what might happen when you need two instantiations of the interface in the same translation unit, but each of those instantiations have different pieced #defineed in. Sounds like a nightmare to me.
Start with a common base class.
class AbstractBaseClass {
// common stuff goes here
};
Then, create abstract interfaces for the sub-versions:
class AbstractSubClass1:public AbstractBaseClass {
public:
void pureVirt1() = 0;
};
class AbstractSubClass2:public AbstractBaseClass {
public:
void pureVirt2() = 0;
};
class AbstractSubClass3:public AbstractBaseClass {
public:
void pureVirt3() = 0;
};
which contain the abstract pureVirt methods.
Finally, derive your implementation classes form the sub classes:
class Derived1 : public AbstractSubClass1 {
virtual void pureVirt1() override; // override if your compiler supports it
};
class Derived2 : public AbstractSubClass2 {
virtual void pureVirt2() override; // override if your compiler supports it
};
class Derived3 : public AbstractSubClass3 {
virtual void pureVirt3() override; // override if your compiler supports it
};
now, objects that know you are a particular sub class can access the pureVirtX member. Those that don't only have access to the common AbstractBaseClass interface (whatever that is - you mention that some code doesn't need to know about these particular virtual methods).
I have two classes A and B where B uses objects of class A, something like this
class A {
private:
int foo_;
A(const int &foo): foo_(foo) {}
}
class B {
// STUFF
inline C operator()(A a)
}
For the moment, I have put the definition of both in a .h file and the code compiles and executes correctly.
My question is: how much can I mask of the implementation of class A, for example by moving code lines to a .cpp file to be separately compiled and linked? Can I mask the implementation of private members and methods (everything which is not directly accessed by an external user)? How? Which C++ keywords should I use?
Thank you very much in advance.
Masking implementations can be done by PIMPL idiom or using simple polymorphism, which is a Factory method pattern. Basically, you create an interface class, say IA like so:
/* File: A.h */
#include <memory> /* For std::shared_ptr */
class IA;
/* Change the line below to boost::shared_ptr<> or
* another implementation of a shared-pointer.
* Read more:
* http://en.wikipedia.org/wiki/Smart_pointer#shared_ptr_and_weak_ptr
*/
typedef std::shared_ptr<IA> APtr;
class IA {
public:
static APtr Create(const int foo);
IA(){}
virtual ~IA(){}
virtual void somePublicMethod() = 0;
};
In your A.cpp you'll have it's implementation:
/* File: A.cpp */
#include "A.h"
class A : public IA
{
public:
A(const int foo):foo_(foo){}
void somePublicMethod(){/* Your awesome implementation goes here */}
};
APtr IA::Create(const int foo)
{
return APtr(new A(foo));
}
This way, you pass around only the interface and expose only the public methods to outside world, which the internals are in your CPP files.
Advantages:
Hide implementation completely from users
Disadvantages:
You'll need to create an interface for every class you intend to hide
Your users will have to call the factory method to create an instance. For e.g. Create() in the above example.
You will always have your class instances to be in heap memory than in stack, i.e., your implementation instances will always have to be a pointer. (Read More: Heap vs. Stack Memory)
If you don't need C operator()(A a) to be inline you could forward declare the parameter A as follows
class A;
Then you can move its definition to another header and include it in the places it's used.
Here are more details about forward declaration.
Regarding what the pImpl idiom can hide:
you can move all function definitions (the implementation thereof, including constructors and their initialisation lists) into the Impl class
which then lets you put private types, data members functions into the Impl class EXCEPT where they affect class behaviour (e.g. private constructors, destructors and operators have implications for the user of the class)
you can move definitions and initialisation of class static data members into the implementation file
as per Arne's comment, private base classes can typically be moved into the implementation (unless you're using typedefs etc. from them in the public or protected data members, and that's ugly as per his comment!)
I have a class that has some data members that I want to be hidden from the caller (because including the headers for their types significantly increases the compile time, and it would require every project using this class to add an additional path to their include paths).
This class uses QSharedDataPointer to store this data. This way it can be copied by using the default copy constructor.
The basic structure of this class is:
class MyClass {
private:
QSharedDataPointer<MySharedClassData> m_data;
};
Is there any fancy trick to do this without defining MySharedClassData (which inherits from QSharedData) in the same header file? Or is there any other good way of hiding data fields?
I've already tried a forward declaration of MySharedClassData but this didn't work (despite the fact that m_data is private).
The only solution I can currently thing of is to declare m_data as QSharedDataPointer<QSharedData> but then I need to cast the data member every time I want to access it. Is there a better solution?
The forward declaration should be working as long as you constructor and destructor are not defined in the header. The following class compiles on my computer:
#ifndef MAIN_WINDOW_HXX
#define MAIN_WINDOW_HXX
#include <QMainWindow>
#include <ui_MainWindow.h>
#include <QSharedDataPointer>
class MySharedClassData;
class MainWindow : public QMainWindow, private Ui_MainWindow {
Q_OBJECT
public:
explicit MainWindow(QWidget *parent = 0, Qt::WindowFlags flags = 0);
virtual ~MainWindow();
QSharedDataPointer<MySharedClassData> m_data;
};
#endif
If you try to inline your constructor/destructor, then you might receive a: C2027: use of undefined type 'type' under VS.
Yes. There's no really fancy trick required. However, all methods that do need MySharedClassData must be defined after the definition of MySharedClassData. If you move the class definition to a .cpp file, the methods have to be moved there too.
In general, if you want to use the pimpl idiom with a smart pointer to a forward-declared impl (rather than managing the impl object manually), you need a smart pointer with an out-of-line deleter, like boost::shared_ptr (you should be able to use std::unique_ptr with a custom deleter, but I haven't tried).
The requirement is that you can instantiate the smart pointer template without seeing the impl class destructor: this rules out std::auto_ptr for example.
I don't know whether QSharedDataPointer meets the requirement or not, but tibur seems to say it does.
So, I am willing to structure my project like that:
ClassA.cpp:
class ClassA {
public:
static ClassA* create() {
return new ClassA();
}
void methodA() {
// stuff here
}
void methodB() {
// more stuff here
}
private:
ClassA() {
}
void privateMethodOne() {
//yadda yadda
}
int attributeA;
char attributeB;
};
ClassA.hpp:
class ClassA {
public:
ClassA* create();
void methodA();
void methodB();
private:
ClassA();
};
I am going to work only with pointers, I wonder if this approach would generate an error in a future. I wonder if there is a pitfall here. Suppose that the .hpp is automatically generated so it would have exactly the same members, except the private ones.
This approach is not valid. C++ has the one definition rule. See C++03 section 3.2 for full details, but here is Wikipedia's summary (highlighting is mine):
In short the ODR states that:
In any translation unit, a template, type, function, or object can have no more than one definition. Some of these can have any number of declarations. A definition provides an instance.
In the entire program, an object or non-inline function cannot have more than one definition; if an object or function is used, it must have exactly one definition. You can declare an object or function that is never used, in which case you don't have to provide a definition. In no event can there be more than one definition.
Some things, like types, templates, and extern inline functions, can be defined in more than one translation unit. For a given entity, each definition must be the same. Non-extern objects and functions in different translation units are different entities, even if their names and types are the same.
You may be looking for the PIMPL idiom, which is a way to "hide" private members from the public interface (i.e. the public header file).
As the OP expressed a wish to:
"...hide the private attributes so you dont have to deploy new headers if the amount of attributes changes"
then I would solve this by seperating interface from implementation. You expose the interface and hide the implementation.
What you could expose to those needing to use the class is a thin interface instead of a class declaration. A thin interface in C++ is best described with pure virtual functions. You would also expose a function which returns the object that implements this interface.
Firstly the header file which exposes your API. This is all the users of the service will see:
struct Interface1 {
virtual ~Interface1() {}
virtual void methodA()=0;
};
Interface1* createInstanceOfInterface1();
Then in files that the user of your service does not see we have the implementation:
class Interface1Impl : public Interface1 {
private:
int nTopSecretMemberVar;
public:
virtual void methodA() {
//implement it
}
};
Interface1* createInstanceOfInterface1() {
return new Interface1Impl();
}
And the usage of your API by the peoplse using the service who are not exposed to the details of the implementation, as follows:
void test() {
Interface1* p = createInstanceOfInterface1();
p->methodA();
}
This becomes a particularly valuable practice when it makes sense to place the implementation of such services in DLLs or shared libraries that can be plugged and played at run time. It yields many benefits.
This is actually double definition of class A
i have a variable that i prefer to declare in a cpp file instead of the header file. It should be accessible to objects of that class only. This variable should have a separate copy for every object of that class. Inheritance is not necessary.
Normally, I'd just declare it in the class definition.
A.h:
class A {
private:
int number;
}
But, can I do this instead?
B.h:
class B {
private:
// nothing
}
B.cpp:
static int number;
No, if you take the second approach, you're making it a static variable, which means you won't have a different copy for each object of that class (they'll all share that variable).
Either way, if it should only be accessed by that class, it should go in the class declaration, and should not be a global variable. By making it a static global variable, you're restricting access just to the scope of the file, not to the class. As good programming practice, try using as few global variables as possible.
If your goal is to hide implementation details from a customer who only sees your header files (either for secrecy, or to avoid dependencies on library internals), the design pattern you're looking for is the pimpl pattern ("pointer to implementation").
myclass.h:
class MyClassImpl;
class MyClass
{
public:
MyClass();
~MyClass();
int someFunc();
private:
MyClassImpl * pimpl;
}
myclass.cpp:
class MyClassImpl
{
public:
MyClassImpl();
int someFunc();
private:
// whatever members you actually need
}
MyClass::MyClass()
{
pimpl = new MyClassImpl();
}
MyClass::~MyClass()
{
delete pimpl;
}
int MyClass::someFunc()
{
return pimpl->someFunc();
}
// go on implementing MyClassImpl as you would have implemented MyClass
Beware: This example code does not have proper copy semantics. You might want to use some smart pointer instead, or implement the proper copy constructor / assignment operator shenannigans.
It is possible to hide data members in the cpp file using the private implementation idiom.
//a.hpp
struct AData;
class A
{
public:
A();
private:
AData* data_members;
};
//a.cpp
struct AData
{
int number;
};
A::A(): data_members(new AData()) {}
Not sure if it pays off with just one integer. But this can be used to reduce compile times: you can modify A's "data members" and implementation at will without having to recompile files including a.hpp.
Also, prefer a suitable smart pointer instead of the plain pointer (one that has suitable copy behavior and can be declared with an incomplete type).
This variable should have a separate copy for every object of that class.
Keeping it static wont let you acheive this. It will be one copy shared by all instances.
If you want each object to have its own copy of number then you will have to make it an member of your class.
If you want a separate copy for every object of your class, you need to declare it in the header file or have some sort of static map between the object value and the value for that object that is initialized by the object constructor.
If you want a variable to be associated with a class object, it has to be declared inside the class. All the object data should be inside the class.
That is called Encapsulation.