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!)
Related
I'm trying to use interface classes and I have the following class structure:
IBase.h:
#pragma once
class IBase
{
protected:
virtual ~IBase() = default;
public:
virtual void Delete() = 0;
IBase& operator=(const IBase&) = delete;
};
IQuackable.h:
#ifndef IQUACKABLE
#define IQUACKABLE
#include "IBase.h"
#include <iostream>
class IQuackable : public IBase
{
protected:
IQuackable() = default;
~IQuackable() = default;
public:
virtual void Quack() = 0;
static IQuackable* CreateInstance();
};
#endif //
MallardDuck.h:
#pragma once
#include "IQuackable.h"
class MallardDuck : public IQuackable
{
private:
MallardDuck();
protected:
~MallardDuck();
public:
void Delete() override;
void Quack() override;
friend IQuackable* IQuackable::CreateInstance();
};
MallardDuck.cpp:
#include "MallardDuck.h"
MallardDuck::MallardDuck() {}
MallardDuck::~MallardDuck() {}
void MallardDuck::Delete() { delete this; }
void MallardDuck::Quack()
{
std::cout << "Quack!\n";
}
IQuackable* IQuackable::CreateInstance()
{
return static_cast<IQuackable*>(new MallardDuck());
}
Also I've created class RedHeadDuck.h and .cpp with the same declaration and definition as MallardDuck.
And, finaly, main class code:
#include "MallardDuck.h"
#include "RedHeadDuck.h"
int main()
{
IQuackable* mallardDuck = MallardDuck::CreateInstance();
IQuackable* redHeadDuck = RedHeadDuck::CreateInstance();
mallardDuck->Quack();
redHeadDuck->Quack();
}
And here I got two errors:
LNK2005 "public: static class IQuackable * __cdecl IQuackable::CreateInstance(void)" (?CreateInstance#IQuackable##SAPAV1#XZ) already defined in MallardDuck.obj".
LNK1169 "one or more multiply defined symbols found".
As I find out, the problem is in double definition, but how it fix?
I've read about Header guards, but, as I understood, it can't help in this case. Also people write about inline functions, but I've not realized how it may be used here.
What can I do?
Goals
I suppose these are what you are trying to obtain by adopting all the complicated patterns:
interface, i.e., "multiple types, same set of methods"
some sort of abstract factory pattern, i.e., you want a "instantiator" who provides a static method (which is not very different from a global function) to call, and returns instances of derived classes
prohibit users from directly calling the ctors of derived classes
take care of the dtors by implementing the Delete() method
Requirement 1-3
There are at least 3 ways to meet requirement 1-3, as explained below:
1. Derived classes hiding static method of their base
This is the easiest way, and it's fully capable of current main.cpp. Derived classes can override static methods of their base class.
In file MallardDuck.h and RedHeadDuck.h:
// Replace this:
// friend IQuackable* IQuackable::CreateInstance();
// With this:
static IQuackable* CreateInstance();
In file MallardDuck.cpp (and RedHeadDuck.cpp similarly):
// Replace this:
// IQuackable* IQuackable::CreateInstance() {
// return static_cast<IQuackable*>(new MallardDuck());
// }
// With this:
IQuackable* MallardDuck::CreateInstance() {
return new MallardDuck();
}
The problem with this is that: other derived classes that don't override and hide CreateInstance() will still expose IQuackable::CreateInstance() as a "fallback". Thus:
if you don't actually implement IQuackable::CreateInstance() (so far, you don't have to), then once it is called via a derived class, the code won't compile and won't give a reason that's comprehensible to others; or
if you choose to implement it, you'd better throw an exception within it, which may surprise your user; otherwise you would have to return a nullptr or something, which is the worst practice in C++ (that's what we do in C since it has no language-level support for error handling; any C++ function that cannot fulfill its job should never return).
Either way is not elegant.
2. Adopt abstract factory pattern
This pattern requires a cooperating "factory class", which is abstract; then whenever you derive a concrete quackable, derive also its factory.
In your case you'll need to sketch out a IQuackableFactory, exposing IQuackableFactory::CreateInstance(), then derive a MallardDuckFactory and a RedHeadDuckFactory.
There are plenty of good examples already, so I won't demonstrate here.
3. Feature injection by using CRTP
There's yet another way of doing things. By CreateInstance() you're actually providing a "Give me an instance of this class!" feature. Typically we use the CRTP (curiously recurring template pattern) to "inject" a certain feature into a class.
First write this file EnableCreateInstance.hpp:
#ifndef _ENABLECREATEINSTANCE_HPP_
#define _ENABLECREATEINSTANCE_HPP_
template <class T>
struct EnableCreateInstance {
static T* CreateInstance() { return new T(); }
};
#endif //_ENABLECREATEINSTANCE_HPP_
Then in MallardDuck.h:
// Add:
#include "EnableCreateInstance.hpp"
class MallardDuck : public IQuackable, public EnableCreateInstance<MallardDuck> {
private:
MallardDuck();
friend class EnableCreateInstance<MallardDuck>;
...
In file RedHeadDuck.h do the similar: include header, publicly inherit EnableCreateInstance<RedHeadDuck>, and declare EnableCreateInstance<RedHeadDuck> as friend class.
This provides more flexibility: you're still providing an interface CreateInstance(), but in a less "aggressive" way: derived classes have their freedom to choose whether or not to provide CreateInstance(). If they do, just inherit and (if ctor made private) declare friendship; if not, omit the additional inheritance.
Requirement 4
Well, actually you can use delete this in non-static non-dtor method. But:
You must ensure (which can be difficult) that no more access to the deleted object's data members or virtual functions are made, otherwise it causes undefined behaviors;
You leave your users with dangling pointers to the deleted object.
So, we seldom provide such "deleters" in modern C++. You can get all the benefits it may provide through smart pointers, plus the ability to avoid UBs and so much more.
Update
The actual context is that I need to create a package to submit to NIST, trying to test a Facial Recognition Algorithm I am working on. The API to use can be found at NIST API and the project to git is at git project
Some code to make a summary of the scenario:
a.h - interface A, composed by pure virtual methods and one static method (frvt11.h at NIST project)
class A {
public:
virtual ~A() {}
virtual void pure_virtual_method_a() = 0;
virtual void pure_virtual_method_b() = 0;
static int static_method();
}
b.h - header file for b.cpp, where interface A's methods are implemented
#include "a.h"
class B : A {
public:
void pure_virtual_method_a();
void pure_virtual_method_b();
static int static_method();
}
b.cpp - Implementation of interface A's methods.
#include "b.h"
void pure_virtual_method_a() {/*implementation*/};
void pure_virtual_method_b() {/*implementation*/};
int static_method() {/*implementation*/};
c.cpp - A file with only a main method and where I want to instantiate an object of B to use its methods.
#include "b.h"
int main(){
B obj;
obj.pure_virtual_method_a();
return 0;
}
Question 1: To instantiate an object of B in c.cpp, do I need to write the header file b.h like above? That seems to be so redundant! It looks like interface A is so unnecessary :-(
Question 2: Is the code presented the right way to implement interface A, and use an object of type B?
Question 3: Do I need to declare a constructor for B in b.h and implement it in b.cpp?
Question 1
You miss a semicolon after the closing curly brace, and it is better to specify that the pure virtual methods you implement in B are marked as override. This allows the compiler to emit warnings in case you forget to change any of the overridden method declarations as soon as the corresponding pure virtual methods in A would change. Thus you will end up with:
#include "a.h"
struct B : public A {
void pure_virtual_method_a() override;
void pure_virtual_method_b() override;
static int static_method();
};
From this it is also clear that for the compiler to be able to declare B as a type, A needs to be declared as well. For example, how would the compiler check the override keyword if it did not yet already have a declaration of A. In case you would not have any overridden virtual methods, A still needs to be known, since the compiler needs to be able to deduce the size of B.
Furthermore, as mentioned in the comments, declaring B as a struct allows you to drop the public keyword, since the default visibility of a struct is public in contrast with private default visibility for a class. This is the only difference between classes and structs in C++. Thus, for interfaces, using structs is more natural.
Question 2
Not completely. b.cpp should look something along the following lines:
#include "b.h"
void B::pure_virtual_method_a() {/*implementation*/};
void B::pure_virtual_method_b() {/*implementation*/};
int B::static_method() {/*implementation*/};
Otherwise, you declare and define three methods in the global namespace, and the linker will complain about undefined references to the three methods of B declared in b.h.
Furthermore, B needs to know how to derive from A, either publicly, protected, or private.
Furthermore, it is a good idea to add include guards to the header files, to prevent the compiler from seeing the same type declaration twice when compiling an object file like a.o or b.o:
#ifndef B_H
#define B_H
#include "a.h"
struct B : public A {
...
};
#endif
Finally, static_method() needs an implementation for A as well, static methods can not be virtual.
Question 3
You do not need to implement a constructor for B necessarily. In case you do not define one, the compiler will generate a default constructor for B. However, in case you define a non-default constructor for A, you will need to define one for B in case you want to construct instances of type B. The constructor can be implemented inline in the header file, or can be defined in b.cpp.
Question 1.
You can use Factory Pattern, then u can add b.h only in Factoru files? and return pointers or smart pointer to A class. For eample, it can be factory function like:
std::unique_ptr<A> getObject(/*params*/)
{
return std::make_unique<B>(/*params*/)
}
And then in c.cpp file:
auto obj = getObject(/*params*/);
obj->pure_virtual_method_a();
Then you can create another implementations of A interface, and return them from factory.
Question 2.
should be class B : public A
and
void B::pure_virtual_method_a() {/*implementation*/};
void B::pure_virtual_method_b() {/*implementation*/};
int B::static_method() {/*implementation*/};
Question 3.
If you need constructor in class A or constructor exactly for class B, you need to define and implement B class constuctor.
How can I add my own method to a pre-existing class without any change in context of pre-existing class.
for example :
A.hpp
class A
{
public :
void print1()
{
cout << "print1";
}
};
B.hpp
//add a helper function to class A
//for example:
A::print2()
{
cout << "print2";
}
main.cpp
#include "A.hpp"
#include "B.hpp"
main()
{
A a1;
a1.print2();
}
To extend a class in C++, distinguish two cases.
If the new function can be expressed in terms of the current interface, use non-member functions
// B.hpp
void print2(A const& a)
{
// pre-call extensions (logging, checking etc.)
a.print1();
// post-call extensions (logging, checking etc.)
}
If the new function requires knowledge about the current implementation, use class inheritance
// B.hpp
// WARNING: here be dragons, read on before using this in production code
class B: public A
{
public:
void print2() const // compiler-generated signature: void print2(B const*)
{
// pre-call extensions (logging, checking etc.)
print1();
// post-call extensions (logging, checking etc.)
}
};
However, deriving from a class that was not intended to be a base class, can be dangerous. In particular, if A does not have a virtual destructor, you can get into trouble if you ever use pointers to dynamically allocated B objects in places where they would be deallocated as if they were pointers to A objects.
Furthermore, because A::print1() was not made virtual, you get into all sorts of name hiding problems, which is why you have to name the extended function B::print2().
Long story short: know which kind of classes you are writing. If you want to extend the behavior based on a class implementation, then you better make it suitable as a base class (virtual destructor, virtual functions that you can override). Otherwise, mark your class as final (new C++11 contextual keyword). This will generate compiler warnings if you try to override existing functions.
NOTE: In other languages (notably D), it is possible to let the compiler automatically find non-member functions print2(a) when it sees the syntax a.print2(). Unfortunately, such uniform function call syntax is not on the roadmap yet for C++.
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.
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.