In any case, A::Stuff is protected, so why inheriting from A and forcing its members' accessibility to protected resulting in an error ?
class A {
protected:
template <typename T>
static void Stuff() {
T::template Stuff<T>();
}
};
class B : protected A {
public:
void something() { A::Stuff<B>(); }
// I have these two, inelegant workarounds:
// using A::Stuff; // KO: This is wrong, it changes the accessibility of Stuff.
// class B : public A // KO: Accessibility changed.
// friend A; // OK: This seems fine.
};
int main() {
B b;
b.something();
}
Code available at: https://godbolt.org/z/r1Ya3rzsK
Assuming the classes A and B as defined above clang and gcc will give you something like that:
'Stuff' is a protected member of 'A'
T::template Stuff<T>();
I give a workaround in the comment and more are welcome as long as the members' accessibility is not changed.
The problem is that the A::Stuff<B>() will call T::Stuff<T>() with T=B aka B::Stuff<B>(). B doesn't have a Stuff function, so it will try falling back to A::Stuff which is invalid, as you made the inheritance protected. (btw if it was valid, because the inheritance was public that would lead to an infinite recursion).
I think you don't want an infinite recursion here. If you want Stuff<B> to be valid add a Stuff function to B.
#include <iostream>
class A {
protected:
template <typename T>
static void Stuff() {
std::cout<<"called A\n";
T::template Stuff<T>();
}
};
class B : protected A {
public:
void something() { A::Stuff<B>(); }
template <typename T>
static void Stuff() {
std::cout<<"called B\n";
//...
}
// I have these two, inelegant workarounds:
// using A::Stuff; // KO: This is wrong, it changes the visibility of Stuff.
// class B : public A // KO: Visibility changed.
// friend A; // OK: This seems fine.
};
int main() {
B b;
b.something();
}
Related
I have two classes using the Curiously Reoccurring Template Pattern with a parent class.
When I compile on VS2013 I get two errors, one for each subclass, stating:
'Parent<Child1>::_child' uses undefined struct 'Child1'
'Parent<Child2>::_child' uses undefined struct 'Child2'
Am I including the files incorrectly, or do I need to make some sort of forward declaration?
Child1.h
#include "Parent.h"
struct Child1 : public Parent<Child1>
{
void init()
{
sharedCode();
}
};
Child2.h
#include "Parent.h"
struct Child2 : public Parent<Child2>
{
void init()
{
sharedCode();
}
};
Parent.h
template<class CHILD>
struct Parent
{
void sharedCode()
{
}
CHILD _child;
};
main.cpp
#include "Child1.h"
#include "Child2.h"
int main()
{
Child1 c1;
Child2 c2;
}
When using the recurring template pattern, the child is an incomplete type in the scope of the parent.
template<class CHILD>
struct Parent
{
CHILD _child; // <- there, incomplete
};
You cannot instantiate an incomplete type as its definition is not there yet.
So... why is that?
A type become complete when the compiler encounter the closing bracket:
struct Hello {
// Technically not complete yet
};
// Complete here, we encountered the closing bracket.
Also, parent classes are required to be complete type themselves:
struct Incomplete;
struct NiceTry : Incomplete {}; // ERROR! `Incomplete` is an incomplete type.
So we have two rules here: the parent of a class must be complete, and a type is not complete until the closing bracket. Inside the parent of a CRTP, we fail both condition: The parent is evaluated before the class scope (they are also positionned before the class scope in the code) and since the parent of a class must be complete, it must be complete before the child class is. You cannot have mutually complete types in class scope, no matter how hard you try:
struct class2;
struct class1 {
// Class 2 is incomplete here
};
struct class2 {
// class1 complete
};
You cannot have both complete at the same time in both scopes.
The same thing happens with CRTP, there is no exceptions there.
Also, your code is roughly equivalent to this:
struct class1 {
class2 instance;
};
struct class2 {
class1 instance;
};
If you try to compute the size of the types, you run into an infinite recursion. You cannot have a type that contain itself.
To fix your problem, don't try to contain the child. Instead, since you know 100% which class is the child, simply cast this:
template<typename Child>
struct parent {
void common_behavior() {
child().function1();
std::cout << child().member1 + child().member2;
}
private:
auto child() noexcept -> Child& { return *static_cast<Child*>(this); }
auto child() const noexcept -> Child const& { return *static_cast<Child const*>(this); }
};
And implement the child like that:
struct child1 : parent<child1> {
void function1() { std::cout << "This is child 1"; }
int member1, member2;
};
struct child2 : parent<child2> {
void function1() { std::cout << "This is child 2"; }
float member1, member2;
};
Live example
My problem with Qt & pimpl is not actually a problem, more a request for best-practice advice.
So: we've got quite a large project with lots of GUI and other Qt classes. Readability of headers is required for fine collaboration, reducing compilation time is also a matter of regular consideration.
Thus, there I have lots of classes like:
class SomeAwesomeClass: public QWidget
{
Q_OBJECT
public:
/**/
//interface goes here
void doSomething();
...
private:
struct SomeAwesomeClassImpl;
QScopedPointer<SomeAwesomeClassImpl> impl;
}
Of course, the Pimpl class is in the .cpp file, works fine, like:
struct MonitorForm::MonitorFormImpl
{
//lots of stuff
}
This piece of software is supposed to be crossplatform (not a surprise) and cross-compiled without significant effort. I know about Q_DECLARE_PRIVATE, Q_D and other macros, they make me think more about Qt MOC, possible differences in Qt versions (because of legacy code), but this way or another there are many lines of code contatinig something like
impl->ui->component->doStuff();
//and
impl->mSomePrivateThing->doOtherStuff()
//and even
impl->ui->component->SetSomething(impl->mSomePrivateThing->getValue());
The pseudo-code above is a much simplified version of the real one, but most of us are fine with it. But some colleagues insist, that it's rather bothering to write and read all those long lines, especially when impl->ui->mSomething-> is repeating too often. The opinion states, that Qt marcos also add visual garbaging to the situation in the end. Seversl #define's could help, but those are considered generally bad practice.
In short, based on your experience, is there a way to make pimpl usage more laconic? Maybe it isn't truly required as often as seems, in non-library classes for example? Maybe the goals of it's usage are not equal, depending on circumstances?
What's the proper way to cook it, anyway?
Introduction
I know about Q_DECLARE_PRIVATE, Q_D and other macros
You know about them, but have you actually used them and understand their purpose, and - for the most part - their inevitability? Those macros weren't added to make stuff verbose. They are there because you end up needing them.
There are no differences in Qt PIMPL implementation between Qt versions, but you are depending on Qt's implementation details when you inherit from QClassPrivate, should you do so. The PIMPL macros have nothing to do with moc. You can use them in plain C++ code that doesn't use any Qt classes at all.
Alas, there's no escaping what you want for as long as you implement the PIMPLs the usual way (which is also Qt way).
Pimpl-pointer vs this
First of all, let's observe that impl stands for this, but the language lets you skip using this-> in most cases. Thus, it's nothing too foreign.
class MyClassNoPimpl {
int foo;
public:
void setFoo(int s) { this->foo = s; }
};
class MyClass {
struct MyClassPrivate;
QScopedPointer<MyClassPrivate> const d;
public:
void setFoo(int s);
...
virtual ~MyClass();
};
void MyClass::setFoo(int s) { d->foo = s; }
Inheritance demands...
Things become generally outlandish when you have inheritance, though:
class MyDerived : public MyClass {
class MyDerivedPrivate;
QScopedPointer<MyDerivedPrivate> const d;
public:
void SetBar(int s);
};
void MyDerived::setFooBar(int f, int b) {
MyClass::d->foo = f;
d->bar = b;
}
You'll want to re-use a single d-pointer in the base class, but it will have the wrong type in all derived classes. Thus you might think of casting it - that's even more boilerplate! Instead, you use a private function that returns a correctly-cast d-pointer. Now you need to derive both public and private classes, and you need private headers for the private classes, so that the derived classes can use them. Oh, and you need to pass the pointer to the derived pimpl to the base class - because that's the only way you can initialize the d_ptr while keeping it const, as it must be. See - Qt's PIMPL implementation is verbose because you do actually need all of it to write safe, composable, maintainable code. No way around it.
MyClass1.h
class MyClass1 {
protected:
struct Private;
QScopedPointer<Private> const d_ptr;
MyClass1(Private &); // a signature that won't clash with anything else
private:
inline Private *d() { return (Private*)d_ptr; }
inline const Private *d() const { return (const Private*)d_ptr; }
public:
MyClass1();
virtual ~MyClass1();
void setFoo(int);
};
MyClass1_p.h
struct MyClass1::Private {
int foo;
};
MyClass1.cpp
#include "MyClass1.h"
#include "MyClass1_p.h"
MyClass1::MyClass1(Private &p) : d_ptr(&p) {}
MyClass1::MyClass1() : d_ptr(new Private) {}
MyClass1::~MyClass1() {} // compiler-generated
void MyClass1::setFoo(int f) {
d()->foo = f;
}
MyClass2.h
#include "MyClass1.h"
class MyClass2 : public MyClass1 {
protected:
struct Private;
private:
inline Private *d() { return (Private*)d_ptr; }
inline const Private *d() { return (const Private*)d_ptr; }
public:
MyClass2();
~MyClass2() override; // Override ensures that the base had a virtual destructor.
// The virtual keyword is not used per DRY: override implies it.
void setFooBar(int, int);
};
MyClass2_p.h
#include "MyClass1_p.h"
struct MyClass2::Private : MyClass1::Private {
int bar;
};
MyClass2.cpp
MyClass2::MyClass2() : MyClass1(*new Private) {}
MyClass2::~MyClass2() {}
void MyClass2::setFooBar(int f, int b) {
d()->foo = f;
d()->bar = b;
}
Inheritance, Qt way
Qt's PIMPL macros take care of implementing d() functions. Well, they implement d_func() and then you use the Q_D macro to obtain a local variable that is simply d. Rewriting the above:
MyClass1.h
class MyClass1Private;
class MyClass1 {
Q_DECLARE_PRIVATE(MyClass1)
protected:
QScopedPointer<Private> d_ptr;
MyClass1(MyClass1Private &);
public:
MyClass1();
virtual ~MyClass1();
void setFoo(int);
};
MyClass1_p.h
struct MyClass1Private {
int foo;
};
MyClass1.cpp
#include "MyClass1.h"
#include "MyClass1_p.h"
MyClass1::MyClass1(MyClass1Private &d) : d_ptr(*d) {}
MyClass1::MyClass1() : d_ptr(new MyClass1Private) {}
MyClass1::MyClass1() {}
void MyClass1::setFoo(int f) {
Q_D(MyClass1);
d->foo = f;
}
MyClass2.h
#include "MyClass1.h"
class MyClass2Private;
class MyClass2 : public MyClass1 {
Q_DECLARE_PRIVATE(MyClass2)
public:
MyClass2();
~MyClass2() override;
void setFooBar(int, int);
};
MyClass2_p.h
#include "MyClass1_p.h"
struct MyClass2Private : MyClass1Private {
int bar;
};
MyClass2.cpp
MyClass2() : MyClass1(*new MyClass2Private) {}
MyClass2::~MyClass2() {}
void MyClass2::setFooBar(int f, int b) {
Q_D(MyClass2);
d->foo = f;
d->bar = b;
}
Factories simplify pimpl
For class hierarchies that are sealed (i.e. where the user doesn't derive), the interface can be sanitized from any private details whatsoever by the use of factories:
Interfaces
class MyClass1 {
public:
static MyClass1 *make();
virtual ~MyClass1() {}
void setFoo(int);
};
class MyClass2 : public MyClass1 {
public:
static MyClass2 *make();
void setFooBar(int, int);
};
class MyClass3 : public MyClass2 {
public:
static MyClass3 *make();
void setFooBarBaz(int, int, int);
};
Implementations
template <class R, class C1, class C2, class ...Args, class ...Args2>
R impl(C1 *c, R (C2::*m)(Args...args), Args2 &&...args) {
return (*static_cast<C2*>(c).*m)(std::forward<Args2>(args)...);
}
struct MyClass1Impl {
int foo;
};
struct MyClass2Impl : MyClass1Impl {
int bar;
};
struct MyClass3Impl : MyClass2Impl {
int baz;
};
struct MyClass1X : MyClass1, MyClass1Impl {
void setFoo(int f) { foo = f; }
};
struct MyClass2X : MyClass2, MyClass2Impl {
void setFooBar(int f, int b) { foo = f; bar = b; }
};
struct MyClass3X : MyClass3, MyClass3Impl {
void setFooBarBaz(int f, int b, int z) { foo = f; bar = b; baz = z;}
};
MyClass1 *MyClass1::make() { return new MyClass1X; }
MyClass2 *MyClass2::make() { return new MyClass2X; }
MyClass3 *MyClass3::make() { return new MyClass3X; }
void MyClass1::setFoo(int f) { impl(this, &MyClass1X::setFoo, f); }
void MyClass2::setFooBar(int f, int b) { impl(this, &MyClass2X::setFooBar, f, b); }
void MyClass3::setFooBarBaz(int f, int b, int z) { impl(this, &MyClass3X::setFooBarBaz, f, b, z); }
This is very basic sketch that should be further refined.
#KubaOber gave an excellent coverage of how pimpl works and how to implement it. One thing not covered that you discussed are the inevitable macros to simplify the boilerplate. Let's take a look at a possible implementation, borrowed from my own Swiss Army knife library, which is clearly based on Qt's take.
Firstly, we need a base public interface and a base private implementation with the boilerplate. Inheriting directly from Qt's implementation is useless if we aren't using Qt (and an incredibly bad idea besides), so we'll just create a lightweight base class for the implementation (or d_ptr) and the implementation's back-pointer to the interface (the q_ptr).
#include <QScopedPointer> //this could just as easily be std::unique_ptr
class PublicBase; //note the forward declaration
class PrivateBase
{
public:
//Constructs a new `PrivateBase` instance with qq as the back-pointer.
explicit PrivateBase(PublicBase *qq);
//We declare deleted all other constructors
PrivateBase(const PrivateBase &) = delete;
PrivateBase(PrivateBase &&) = delete;
PrivateBase() = delete;
//! Virtual destructor to prevent slicing.
virtual ~PrivateBase() {}
//...And delete assignment operators, too
void operator =(const PrivateBase &) = delete;
void operator =(PrivateBase &&) = delete;
protected:
PublicBase *qe_ptr;
};
class PublicBase
{
public:
//! The only functional constructor. Note that this takes a reference, i.e. it cannot be null.
explicit PublicBase(PrivateBase &dd);
protected:
QScopedPointer<PrivateBase> qed_ptr;
};
//...elsewhere
PrivateBase::PrivateBase(PublicBase *qq)
: qe_ptr(qq)
{
}
PublicBase::PublicBase(PrivateBase &dd)
: qed_ptr(&dd) //note that we take the address here to convert to a pointer
{
}
Now to the macros.
/* Use this as you would the Q_DECLARE_PUBLIC macro. */
#define QE_DECLARE_PUBLIC(Classname) \
inline Classname *qe_q_func() noexcept { return static_cast<Classname *>(qe_ptr); } \
inline const Classname* qe_cq_func() const noexcept { return static_cast<const Classname *>(qe_ptr); } \
friend class Classname;
/* Use this as you would the Q_DECLARE_PRIVATE macro. */
#define QE_DECLARE_PRIVATE(Classname) \
inline Classname##Private* qe_d_func() noexcept { return reinterpret_cast<Classname##Private *>(qed_ptr.data()); } \
inline const Classname##Private* qe_cd_func() const noexcept { return reinterpret_cast<const Classname##Private *>(qed_ptr.data()); } \
friend class Classname##Private;
These are fairly self-explanatory: they cast the stored pointer to the appropriate derived type. The macro leverages the class name + "Private" to cast to the right type. This means your private class MUST follow the naming pattern: InterfaceClass becomes InterfaceClassPrivate. For scope resolution to work, they need to be in the same namespace, too. Your private class can't be a member of your public class.
And finally, the accessors, with a C++11 twist:
#define QE_DPTR auto d = qe_d_func()
#define QE_CONST_DPTR auto d = qe_cd_func()
#define QE_QPTR auto q = qe_q_func()
#define QE_CONST_QPTR auto q = qe_cq_func()
Not having to explicitly specify the class name makes usage incredibly easy and less rigid. Should this class be renamed or the function moved to another level in the inheritance hierarchy, you don't have to change the QE_CONST_DPTR statement.
SomeInterface::getFoo() const noexcept
{
QE_CONST_DPTR;
return d->foo;
}
would become:
SomeInterfaceInheritingFromSomeOtherInterface::getFoo() const noexcept
{
QE_CONST_DPTR;
return d->foo;
}
One purpose of PIMPL is to decouple interface from private implementation. Examples like impl->ui->component->doStuff(); are a sign that there is a problem with the scope of the interface. IMHO you should normally not see more than one deep calls.
I.e.
impl->doStuff(); OK
impl->ui->doStuff(); Hmmm, better avoid that.
impl->ui->component->... Uh oh, things go wrong here. Caller needs to know far too much details of the implementation. That's not the purpose of PIMPL!
You may want to read https://herbsutter.com/gotw/_100/, especially the section What parts of the class should go into the impl object?
Given some base interfaces A, B, C.... N
And some hypothetical classes which implement a set of them:
class MyClass1: public A, public B, public N;
class MyClass2: public A, public B, public D;
I would like to create function which accept as parameter an object (or pointer to object) to a class which include, lets say A and B.
void myFunc( A&B obj );
From a C++ programmer perspective, this seem absurd. From a software architect perspective, this seem like the basic bloc that all languages should have.
Is there any trick (except template) or solution for that?
Note: Most of the interfaces do not come from me, so it is (in principle) no possible to make changes on interfaces.
EDITED:
Here some example:
class A{
public:
virtual void draw()=0;
};
class B{
public:
virtual void edit()=0;
};
class AandB: public A, public B
{
virtual void draw()override{};
virtual void edit()override{};
};
//This function know about A, B, but not AandB
void some_function((A+B)& a_and_b) { // That do not work
a_and_b.draw();
a_and_b.edit();
}
int main()
{
AandB c;
some_function(c); // that is not so easy
}
#include <type_traits>
using namespace std;
class A{};
class B{};
template<class T, enable_if_t<is_same<A, decay_t<T>>::value || is_same<B, decay_t<T>>::value, int> = 0>
void some_function(T&& a_or_b) {}
live: https://godbolt.org/g/Z1MV8w
This example requires c++14, but you can use enable_if instead if you need 11 compatibility. It's just not as readable.
If you want to take anything that inherits from either A or B, use is_base_of instead of is_same
What you are really asking for is the compiler to create an intermediate type (A & B) whose interface contains both interface A and interface B. And then to allow any type that implements both those interfaces to bind to a reference of this combined type.
I am not even sure how you might refer to such a gestalt type in syntax:
void func((A+B)& var); // ???
Well you can do a similar thing with current syntax without the compiler creating scaffolding behind the scenes by simply accepting the parameter twice like this:
struct A { void stuff(){ std::cout << "A\n"; } };
struct B { void stuff(){ std::cout << "B\n"; } };
struct C { void stuff(){ std::cout << "C\n"; } };
struct MyType: A, B, C
{
void stuff() { std::cout << "MyType\n"; }
};
void func(A& a, B& b) // accept both interfaces in func
{
a.stuff(); // use interface A
b.stuff(); // use interface B
}
int main()
{
MyType m;
func(m, m); // pass both interfaces to func()
}
I voted on xaxxon answer,
but f you want to do it in "virtual" way,
you can do class that extends A and B.
Will look like this:
class A;
class B;
class A_B: public A, public B{
};
class MyClass1: public A_B, public XXX{
};
class MyClass2: public A_B, public YYY{
};
void myFunc( A_B obj );
I agree this looks suspiciously much like Java.
One way to mitigate cons of template
void myFunc_impl(A& aPart, B& bPart); // aPart and bPart are from the same object.
template <typename T>
void myFunc(T& obj) {
// static_assert to have better error messages
static_assert(std::is_base_of<A, T>::value, "T should inherit from A");
static_assert(std::is_base_of<B, T>::value, "T should inherit from B");
// Forwarding to implementation
myFunc_impl(obj, obj);
}
1) force definition to be in the header, difficult to maintain
You just have the forwarding in the header:
code is short.
2) difficult to manage with polymorphic pointers,
As long as you take reference or pointer, this part if ok with template.
4) It make difficult or impossible some other features like virtual?
Indeed, template method cannot be template, but here, you may forward to a virtual method.
5) Code is difficult to check, as issues are apparent only at usage stage.
You have indeed to instantiate it to see all errors.
According to http://msdn.microsoft.com/en-us/library/9ekhdcxs(v=vs.80).aspx,
C2079 can also occur if you attempt to declare an object on the stack of a type whose forward declaration is only in scope.
class A;
class B {
A a; // C2079
};
class A {};
Possible resolution:
class A;
class C {};
class B {
A * a;
C c;
};
class A {};
My question is how do I eliminate this error when I have the following situation:
class A; // Object
class B // Container
{
public:
typedef int SomeTypedef;
private:
A a; // C2079
};
class A {
void Foo(B::SomeTypedef);
};
I can't declare A before declaring B because A needs to use B's typedef, and I can't declare B before A because of this error.
One possible solution is to use a pointer to A instead of a stack variable, but I don't want a pointer (in this case).
Another solution is to not use typedef, or not to put it inside class B. But what if it belongs in B and I want not to pollute my project's namespace, as in B::SomeTypedef is a more appropriate name than SomeTypedef?
Your design is questionable, although perhaps nested classes is what you intend:
class B {
public:
typedef int SomeTypedef;
private:
class A {
void Foo(SomeTypedef);
};
A a;
};
If not, this can also be solved with another class which is common in CRTP code.
template<typename T>
struct foo;
class A;
class B;
template<>
struct foo<B> {
typedef int SomeTypedef;
};
class A {
void Foo(foo<B>::SomeTypedef);
};
class B : foo<B> {
private:
A a;
};
Or you can use another namespace.
Another method is use an intermediate class, plus pointers, its more long, but, it works:
This is header file, ( yes I know, "*.hpp" extension is not standard ):
ForwardClassExample.hpp
class ForwardClass {
public:
virtual void DoSomething();
};
class ContainerClass {
ForwardClass* Item;
/* constructor */ ContainerClass();
/* destructor */ ~ContainerClass();
};
class RealClass: ForwardClass {
/* override */ virtual void DoSomething();
};
This is body file:
ForwardClassExample.cpp
/* constructor */ ContainerClass::ContainerClass()
{
// create reference to forwaded class item
this.Item = new RealClass();
}
/* destructor */ ContainerClass::~ContainerClass()
{
// deletereference to forwaded class item
free this.Item();
}
void ForwardClass::DoSomething()
{
// ...
}
void RealClass::DoSomething()
{
// ...
}
Note:
I suggest to get used to apply pointers to variables, instead of direct fields, its may looks more difficult, at start, but, eventually allows to do more stuff.
It also prepare you to use "references" in case, one day you have to work with other programming languages.
Cheers.
Introduce the typedef where your design requires it, and then export it to wherever it makes the most sense for your user.
class A
{
public:
typedef int SomeTypedef;
void Foo(SomeTypedef);
};
class B
{
public:
typedef A::SomeTypedef SomeTypedef;
private:
A a;
};
I have a class (class A) that is designed to be inherited by other classes written by other people.
I also have another class (class B), that also inherits from A.
B has to access some A's member functions that shouldn't be accessed by other inheriting classes.
So, these A's member functions should be public for B, but private for others.
How can I solve it without using 'friend' directive?
Thank you.
EDIT: Example why I need it.
class A
{
public:
void PublicFunc()
{
PrivateFunc();
// and other code
}
private:
virtual void PrivateFunc();
};
class B : public class A
{
private:
virtual void PrivateFunc()
{
//do something and call A's PrivateFunc
A::PrivateFunc(); // Can't, it's private!
}
};
You can't. That's what friend is for.
An alternative would be to change the design/architecture of your program. But for hints on this I'd need some more context.
What you say is: there are two sets of subclasses of A. One set should have access, the other set shouldn't. It feels wrong to have only one brand of subclasses (i.e. B) 'see' A's members.
If what you mean is: only we can use this part of functionality, while our clients can't, there are other resorts.
(Functionality reuse by inheritance often corners you with this kind of problems. If you go towards reuse by aggregation, you may get around it.)
A suggestion:
// separate the 'invisible' from the 'visible'.
class A_private_part {
protected:
int inherited_content();
public:
int public_interface();
};
class B_internal : public A_private_part {
};
class A_export : private A_private_part {
public:
int public_interface() { A_private_part::public_interface(); }
};
// client code
class ClientClass : public A_export {
};
But better would be to go the aggregation way, and split the current "A" into a visible and an invisible part:
class InvisibleFunctionality {
};
class VisibleFunctionality {
};
class B {
InvisibleFunctionality m_Invisible;
VisibleFunctionality m_Visible;
};
// client code uses VisibleFunctionality only
class ClientClass {
VisibleFunctionality m_Visible;
};
Well - if you want exactly what you've described, then friend is the best solution. Every coding standard recommends not using friend but where the alternative design is more complex - then maybe it's worth making an exception.
To solve the problem without friend will require a different architecture
One solution might be to use a form of the pImpl idiom where 'B' derives from the inner implementation object, while the other clients derive from the outer class.
Another might be to place an extra layer of inheritance between 'A' and the "other clients". Something like:
class A {
public:
void foo ();
void bar ();
};
class B : public A { // OK access to both 'foo' and 'bar'
};
class ARestricted : private A {
public:
inline void foo () { A::foo (); }; // Forwards 'foo' only
};
However, this solution still has it's problems. 'ARestricted' cannot convert to an 'A' so this would need to be solved by some other "getter" for 'A'. However, you could name this function in such a way as it cannot be called accidentally:
inline A & get_base_type_A_for_interface_usage_only () { return *this; }
After trying to think of other solutions, and assuming that your hierarchy needs to be as you describe, I recommend you just use friend!
EDIT: So xtofl suggested renaming the types 'A' to 'AInternal' and 'ARestricted' to 'A'.
That works, except I noticed that 'B' would no longer be an 'A'. However, AInternal could be inherited virtually - and then 'B' could derive from both 'AInternal' and 'A'!
class AInternal {
public:
void foo ();
void bar ();
};
class A : private virtual AInternal {
public:
inline void foo () { A::foo (); }; // Forwards 'foo' only
};
// OK access to both 'foo' and 'bar' via AInternal
class B : public virtual AInternal, public A {
public:
void useMembers ()
{
AInternal::foo ();
AInternal::bar ();
}
};
void func (A const &);
int main ()
{
A a;
func (a);
B b;
func (b);
}
Of course now you have virtual bases and multiple inheritance! Hmmm....now, is that better or worse than a single friend declaration?
I think you have a bigger problem here. Your design doesn't seem sound.
1) I think the 'friend' construct is problematic to begin with
2) if 'friend' isn't what you want, you need to re-examine your design.
I think you either need to do something that just gets the job done, using 'friend' or develop a more robust architecture. Take a look at some design patterns, I'm sure you'll find something useful.
EDIT:
After seeing your sample code, you definitely need to re-arch. Class A may not be under your control, so that's a little tricky, but maybe want you want to re-do Class B to be a "has-a" class instead of an "is-a" class.
public Class B
{
B()
{
}
void someFunc()
{
A a; //the private functions is now called and a will be deleted when it goes out of scope
}
};
I find this a interesting challenge. Here is how I would solve the problem:
class AProtectedInterface
{
public:
int m_pi1;
};
class B;
class A : private AProtectedInterface
{
public:
void GetAProtectedInterface(B& b_class);
int m_p1;
};
class B : public A
{
public:
B();
void SetAProtectedInterface(::AProtectedInterface& interface);
private:
::AProtectedInterface* m_AProtectedInterface;
};
class C : public A
{
public:
C();
};
C::C()
{
m_p1 = 0;
// m_pi1 = 0; // not accessible error
}
B::B()
{
GetAProtectedInterface(*this);
// use m_AProtectedInterface to get to restricted areas of A
m_p1 = 0;
m_AProtectedInterface->m_pi1 = 0;
}
void A::GetAProtectedInterface(B& b_class)
{
b_class.SetAProtectedInterface(*this);
}
void B::SetAProtectedInterface(::AProtectedInterface& interface)
{
m_AProtectedInterface = &interface;
}
If you where going to use this sort of pattern all the time, you could reduce the code by using templates.
template<class T, class I>
class ProtectedInterfaceAccess : public I
{
public:
void SetProtectedInterface(T& protected_interface)
{
m_ProtectedInterface = &protected_interface;
}
protected:
T& GetProtectedInterface()
{
return *m_ProtectedInterface;
}
private:
T* m_ProtectedInterface;
};
template<class T, class I>
class ProtectedInterface : private T
{
public:
void SetupProtectedInterface(I& access_class)
{
access_class.SetProtectedInterface(*this);
}
};
class Bt;
class At : public ProtectedInterface <::AProtectedInterface, Bt>
{
public:
int m_p1;
};
class Bt : public ProtectedInterfaceAccess<::AProtectedInterface, At>
{
public:
Bt();
};
class Ct : public At
{
public:
Ct();
};
Ct::Ct()
{
m_p1 = 0;
// m_pi1 = 0; // not accessible error
}
Bt::Bt()
{
SetupProtectedInterface(*this);
m_p1 = 0;
GetProtectedInterface().m_pi1 = 0;
}
If I understand:
A will be subclassed by other developers.
B will be subclassed by other developers and inherits from A.
A has some methods you don't want accessible to outside developers through B.
I don't think this can be done without using friend. There is no way I know of to make members of a superclass available only to direct inheritors.