I have a class A in component CA, and classes BPub a BPriv in component CB. In CMake I link CB to CA using target_link_libraries, meaning CA knows the component/library CB. In CB, BPub defines the interface of CB, i.e., it is a class that other components (such as CA) should be able to use. BPriv on the other hand is only used internally in CB and should not be available to the outside of CB.
Because I want BPriv to be hidden to the outside of CB, I exclude BPriv.h and BPriv.cpp from the include directories (target_include_directories). When compiling class A the compiler complains that it cannot open include file BPriv.h.
I understand that A includes BPub which again includes BPriv and as such BPriv has to be known. However, conceptually it seems odd to me that BPriv needs to be known since it is only a private member of BPub and does not appear at all in the public interface int complex_calculation(int num).
Why does A need to know BPriv.h?
How can I hide BPriv.h to the users of CB which want to use the functionality exposed by the public functions in BPub.h?
// A.h
#include "CB/BPub.h"
class A {
public:
int calculate(int num) {
BPub bPub;
return bPub.complex_calculation(num);
}
};
// BPub.h
#include "BPriv.h"
class BPub {
public:
int complex_calculation(int num);
private:
BPriv m_calculator;
};
// BPub.cpp
#include "BPub.h"
int BPub::complex_calculation(int num) {
return m_calculator.calc(num);
}
// BPriv.h
class BPriv {
public:
int calc(int num)
};
// BPriv.cpp
#include "BPriv.h"
int BPriv::calc(int num) {
return do_crazy_calc(num);
}
Related
There is no feature that control visibility/accessibility of class in C++.
Is there any way to fake it?
Are there any macro/template/magic of C++ that can simulate the closest behavior?
Here is the situation
Util.h (library)
class Util{
//note: by design, this Util is useful only for B and C
//Other classes should not even see "Util"
public: static void calculate(); //implementation in Util.cpp
};
B.h (library)
#include "Util.h"
class B{ /* ... complex thing */ };
C.h (library)
#include "Util.h"
class C{ /* ... complex thing */ };
D.h (user)
#include "B.h" //<--- Purpose of #include is to access "B", but not "Util"
class D{
public: static void a(){
Util::calculate(); //<--- should compile error
//When ctrl+space, I should not see "Util" as a choice.
}
};
My poor solution
Make all member of Util to be private, then declare :-
friend class B;
friend class C;
(Edit: Thank A.S.H for "no forward declaration needed here".)
Disadvantage :-
It is a modifying Util to somehow recognize B and C.
It doesn't make sense in my opinion.
Now B and C can access every member of Util, break any private access guard.
There is a way to enable friend for only some members but it is not so cute, and unusable for this case.
D just can't use Util, but can still see it.
Util is still a choice when use auto-complete (e.g. ctrl+space) in D.h.
(Edit) Note: It is all about convenience for coding; to prevent some bug or bad usage / better auto-completion / better encapsulation. This is not about anti-hacking, or prevent unauthorized access to the function.
(Edit, accepted):
Sadly, I can accept only one solution, so I subjectively picked the one that requires less work and provide much flexibility.
To future readers, Preet Kukreti (& texasbruce in comment) and Shmuel H. (& A.S.H is comment) has also provided good solutions that worth reading.
I think that the best way is not to include Util.h in a public header at all.
To do that, #include "Util.h" only in the implementation cpp file:
Lib.cpp:
#include "Util.h"
void A::publicFunction()
{
Util::calculate();
}
By doing that, you make sure that changing Util.h would make a difference only in your library files and not in the library's users.
The problem with this approach is that would not be able to use Util in your public headers (A.h, B.h). forward-declaration might be a partial solution for this problem:
// Forward declare Util:
class Util;
class A {
private:
// OK;
Util *mUtil;
// ill-formed: Util is an incomplete type
Util mUtil;
}
One possible solution would be to shove Util into a namespace, and typedef it inside the B and C classes:
namespace util_namespace {
class Util{
public:
static void calculate(); //implementation in Util.cpp
};
};
class B {
typedef util_namespace::Util Util;
public:
void foo()
{
Util::calculate(); // Works
}
};
class C {
typedef util_namespace::Util Util;
public:
void foo()
{
Util::calculate(); // Works
}
};
class D {
public:
void foo()
{
Util::calculate(); // This will fail.
}
};
If the Util class is implemented in util.cpp, this would require wrapping it inside a namespace util_namespace { ... }. As far as B and C are concerned, their implementation can refer to a class named Util, and nobody would be the wiser. Without the enabling typedef, D will not find a class by that name.
One way to do this is by friending a single intermediary class whose sole purpose is to provide an access interface to the underlying functionality. This requires a bit of boilerplate. Then A and B are subclasses and hence are able to use the access interface, but not anything directly in Utils:
class Util
{
private:
// private everything.
static int utilFunc1(int arg) { return arg + 1; }
static int utilFunc2(int arg) { return arg + 2; }
friend class UtilAccess;
};
class UtilAccess
{
protected:
int doUtilFunc1(int arg) { return Util::utilFunc1(arg); }
int doUtilFunc2(int arg) { return Util::utilFunc2(arg); }
};
class A : private UtilAccess
{
public:
int doA(int arg) { return doUtilFunc1(arg); }
};
class B : private UtilAccess
{
public:
int doB(int arg) { return doUtilFunc2(arg); }
};
int main()
{
A a;
const int x = a.doA(0); // 1
B b;
const int y = b.doB(0); // 2
return 0;
}
Neither A or B have access to Util directly. Client code cannot call UtilAccess members via A or B instances either. Adding an extra class C that uses the current Util functionality will not require modification to the Util or UtilAccess code.
It means that you have tighter control of Util (especially if it is stateful), keeping the code easier to reason about since all access is via a prescribed interface, instead of giving direct/accidental access to anonymous code (e.g. A and B).
This requires boilerplate and doesn't automatically propagate changes from Util, however it is a safer pattern than direct friendship.
If you do not want to have to subclass, and you are happy to have UtilAccess change for every using class, you could make the following modifications:
class UtilAccess
{
protected:
static int doUtilFunc1(int arg) { return Util::utilFunc1(arg); }
static int doUtilFunc2(int arg) { return Util::utilFunc2(arg); }
friend class A;
friend class B;
};
class A
{
public:
int doA(int arg) { return UtilAccess::doUtilFunc1(arg); }
};
class B
{
public:
int doB(int arg) { return UtilAccess::doUtilFunc2(arg); }
};
There are also some related solutions (for tighter access control to parts of a class), one called Attorney-Client and the other called PassKey, both are discussed in this answer: clean C++ granular friend equivalent? (Answer: Attorney-Client Idiom) . In retrospect, I think the solution I have presented is a variation of the Attorney-Client idiom.
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 would like to implement the expose module in derived class (.h or .cpp file). its work fine, when I exposed this in main in one BOOST_PYTHON_MODULE but when I exposed differently in abstract and derived class its get error one or more multiply defined symbols errors. the example code is as follows.
**Base.h**
class Base
{
public:
virtual void Set(const std::vector<std::string>& AllParameters) = 0;
};
struct BaseWrap : Base, wrapper<Base>
{
void Set(const std::vector<std::string>& AllParameters)
{
this->get_override("Set")(AllParameters);
}
**Base.cpp**
BOOST_PYTHON_MODULE(Example)
{
class_<Basewrapper , boost::noncopyable> ("Base")
.def("Set",pure_virtual(&Base::Set))
;
}
**Derived.h**
class Derived : public Base
{
public:
int test(int a, int b);
};
BOOST_PYTHON_MODULE(Example)
{
class_<Derived , boost::noncopyable> ("Derived")
.def("test",&Derived ::test)
;
}
**Derived.cpp**
void Derived:: test(int a , int b)
{
return a+b;
}
The BOOST_PYTHON_MODULE macro defines a function with identifiers based on the provided argument. Hence, defining the Example module in both Base.cpp and Derived.h violates the one definition rule when linking them into the same library. To resolve this, consider splitting the function bodies that export each individual class into their own functions (i.e. export_base() and export_derived()), and have a single file (example.cpp) that defines BOOST_PYTHON_MODULE with a body that invokes the other export functions. This technique can be seen here.
I am writing a shared library (call it MyLib) which depends on another library (call it ParentLib). The ParentLib has a few virtual functions which I am implementing in MyLib along with several other independent implementations.
// MyLib.h
#include <parentlib_library.h>
class Foo : public ClassinParent
{
public:
void DefinitionofParentLibFunction();
private:
// ...
};
I was able to compile and generate the MyLib with no issues but when the MyLib is used by the application, I need to include the ParentLib_library.h to compile the code.
One of my requirements is that the ParentLib should be completely hidden from the application. I am not sure of the next step to achieve this.
Any ideas?
If your declaration used in callback or implementation of interface from 3dparty lib - then no way. In all another cases I usually apply following 3 approaches.
1) Use aggregation. Declare ClassInParent as forward and use as member of Foo:
class ClassInParent;//forward declare
class Foo
{
ClassInParent* _inst; //use either pointer of reference to external
public:
void method_of_ClassInParent() //make facade for parent methods if needed
}
2) Separate your class into interface (that is not depended on ClassInParent) and implementation (that is not expose via #include)
Your Foo.h:
class Foo
{
public:
virtual void do_smth() = 0;
};
Your Foo.cpp:
#include <parentlib_library.h>
class FooImpl : public Foo, public ClassInParent
{
void do_smth()
{//implementation
3) Use templates. Instead of explicit inherience use template:
template <class T>
class Foo : public T
{
Later in your code Foo<ClassInParent>
if i want to have 3 classes, which have common fields (and i want them to be static)
and they have a common function (which needed to be overridden, i.e virtual)
what the best design to do this?
do i need to create an interface in a header file
and then create it's .cpp file and get the 3 classes inheritance from it?
what about the static members?
can i declare them in the header file?
when creating header file which representing interface, do i have to create it's .cpp file?
Declare the classes in header files.
This is so that the declaration can be shared between multiple source files (with #include) and thus obey the (One definition rule).
It is traditional (though not required) that each class has its own file. To make it consistent and easy to find things you should name the file after the class. So Class A should be declared in A.h and defined in A.cpp.
MyInterface.h
class MyInterface
{
protected:
static int X;
static int Y;
static int Z;
public:
// If a class contains virtual functions then you should declare a vritual destructor.
// The compiler will warn you if you don't BUT it will not require it.
virtual ~MyInterface() {} // Here I have declared and defined the destructor in
// at the same time. It is common to put very simplistic
// definitions in the header file. But for clarity more
// complex definitions go in the header file. C++ programers
// dislike the Java everything in one file thing because it
// becomes hard to see the interface without looking at the
// documentaiton. By keeping only the declarations in the
// header it is very easy to read the interface.
virtual int doSomthing(int value) = 0; // Pure virtual
// Must be overridden in derived
};
A.h
#include "MyInterface.h"
class A: public MyInterface
{
public:
virtual int doSomthing(int value);
};
B.h
#include "MyInterface.h"
class B: public MyInterface
{
public:
virtual int doSomthing(int value);
};
C.h
#include "MyInterface.h"
class C: public MyInterface
{
public:
virtual int doSomthing(int value);
};
Now you define the implementation in the source files:
MyInterface.cpp
#include "MyInterface.h"
// Static members need a definition in a source file.
// This is the one copy that will be accessed. The header file just had the declaration.
int MyInterface::X = 5;
int MyInterface::Y = 6;
int MyInterface::Z = 7;
A.cpp
#include "A.h"
// Define all the methods of A in this file.
int A::doSomthing(int value)
{
// STUFF
}
B.cpp
#include "B.h"
int B::doSomthing(int value)
{
// STUFF
}
C.cpp
#include "C.h"
int C::doSomthing(int value)
{
// STUFF
}
There is no explicit "interface" thing in the C++ language.
If you'd like to have an interface-like class, that's a class with pure virtual methods (that is a method w/o definition, e.g. virtual void printme() = 0;).
Static variables are bound to object files (internal linkage). If you define them in your header file and include that header file into several cpp files, you'll end up having several definitions of that static variable (in different object files)
Since static variables are either global or part of a class, they cannot be 'common'. They belong to one class and may be accessed by another one.
Same goes for methods. One class has a method, another one may call it. If it's a derived class, it may also override it (that is either hide it or implement a virtual method).
Now, if you have three classes that have the same structure, you may (or may not) like to inherit them from a base class for several reasons. One is to avoid copying code. Another one is the main reason, that you may want to treat objects from the derived classes all the same, let's say you have a vehicle that you can use, but the vehicle may be a car, a bike or a plane. You want to use a vehicle, but don't mind which vehicle it actually is, so you create
class Vehicle
{
public:
virtual void use() = 0;
};
class Car
: public Vehicle
{
public:
virtual void use();
};
void Car::use()
{
// drive the car
}
Than you can use a Car as vehicle, for example
Car myCar;
Vehicle& myVehicle = static_cast< Vehicle& >(myCar);
myVehicle.use(); // drive the car.
That all is fundamental C++ OOP, look it up in some book.