What do I have (simplified version):
template<typename T> class Watcher
{
public:
T* m_watched { nullptr };
Watcher() = default;
Watcher(T* watched) : m_watched(watched) { m_watched->addWatcher(this); };
virtual void notifyChange(int = 0) /*= 0*/{std::cout << "Watcher::notifyChange()\n";};
};
template<typename T> class Watchable
{
public:
std::vector<Watcher<T>*> m_watchers;
virtual void addWatcher(Watcher<T>* watcher)
{
m_watchers.push_back(watcher);
watcher->notifyChange();
}
};
class Config : public Watchable<Config>
{
};
class Property : public Watcher<Config>
{
public:
Property(Config* config) : Watcher<Config>(config) {};
void notifyChange(int = 0) override { std::cout << "Property::notifyChange()\n"; }
};
So when I create an instance of Property notifyChange() of the base class (Watcher) is called.
I understand why this happens, but I have no idea how to fix this still having proper modern C++ code (e.g. without making m_watched protected and so on).
You can't.
During construction of the base, the derived sub-object doesn't exist yet.
You could try making a factory function instead, which takes control of creating Propertys. Then it can instantiate in one step, and register in a second step. Make the factory function a friend as needed and have all the related machinery be otherwise private.
Vaguely related blog article
Related
I want to design a component-based weapon template for my game. However, it seems no way to add/remove a class member or create a code?
Sorry for my expression and lack of terminology, for I am not graduated from dept. of computer science or software engineer, I know little of what those stuff called by professionals.
Here is the component code looks like:
class CBaseWpnCmpt : public std::enable_shared_from_this<CBaseWpnCmpt>
{
public:
typedef std::shared_ptr<CBaseWpnCmpt> PTR;
private:
CBaseWpnCmpt() = default;
public:
CBaseWpnCmpt(const CBaseWpnCmpt& s) = default;
CBaseWpnCmpt(CBaseWpnCmpt&& s) = default;
CBaseWpnCmpt& operator=(const CBaseWpnCmpt& s) = default;
CBaseWpnCmpt& operator=(CBaseWpnCmpt&& s) = default;
virtual ~CBaseWpnCmpt() {}
protected:
CBaseWeaponInterface::PTR m_pWeapon { nullptr };
public:
template <class CComponent>
static std::shared_ptr<CComponent> Create(CBaseWeaponInterface::PTR pWeapon)
{
std::shared_ptr<CComponent> pComponent = std::make_shared<CComponent>();
pComponent->m_pWeapon = pWeapon;
return pComponent;
}
};
And this is what a weapon body code looks like: (And the problem occurs)
template < class CWeapon,
class ...CComponents
>
class CBaseWeaponTemplate : public CBaseWeaponInterface
{
public:
std::list<CBaseWpnCmpt::PTR> m_lstComponents;
public:
virtual void SecondaryAttack(void) // Example method.
{
for (auto& pComponent : m_rgpComponents)
{
pComponent->SecondaryAttack();
}
}
};
How am I suppose to create all these argument packs as member of the template? Currently I tried to enlist them into a pointer std::list container, but I just can't figure out how to achieve it at all.
In other words, how can I make a template when I fill in blank likt this:
class CAK47 : public CBaseWeaponTemplate<CAK47, CLongMagazine, CWoodenStock>
will generate this:
class CAK47
{
CLongMagazine m_comp1;
CWoodenStock m_comp2;
//... other stuff
};
Or alternatively, generate this:
class CAK47
{
CAK47() // constructor
{
for (/* somehow iterate through all typenames */)
{
CBaseWpnCmpt::PTR p = std::make_shared<typename>();
m_lstComponents.emplace_back(p);
}
}
};
One way of doing so from C++11 on-wards would be to store the template types used for this particular weapon inside an std::tuple
template <typename Weapon, typename... Attachments>
class WeaponWithAttachments {
protected:
WeaponWithAttachments() {
return;
}
std::tuple<Attachments...> attachment_types;
};
and then using that tuple to initialise a vector of shared pointers with a protected constructor taking a tuple to access the template types again.
class SomeWeaponWithAttachments: public WeaponWithAttachments<SomeWeapon,SomeAttachment,AnotherAttachment> {
public:
SomeWeaponWithAttachments()
: SomeWeaponWithAttachments{attachment_types} {
return;
}
protected:
template <typename... Attachments>
SomeWeaponWithAttachments(std::tuple<Attachments...> const&)
: attachments{std::make_shared<Attachments>()...} {
return;
}
std::vector<std::shared_ptr<BaseAttachment>> attachments;
};
Try it here!
If the attachments vector is already declared inside the parent class like it seems to be the case for you might also avoid the tuple and the protected constructor with initialising the attachments already inside the parent class
template <typename Weapon, typename... Attachments>
class WeaponWithAttachments {
protected:
WeaponWithAttachments()
: attachments{std::make_shared<Attachments>()...} {
return;
}
std::vector<std::shared_ptr<BaseAttachment>> attachments;
};
and then only calling the constructor of the base class in the derived class
class SomeWeaponWithAttachments: public WeaponWithAttachments<SomeWeapon,SomeAttachment,AnotherAttachment> {
public:
SomeWeaponWithAttachments()
: WeaponWithAttachments<SomeWeapon,SomeAttachment,AnotherAttachment>() {
return;
}
};
Try it here!
If that is no option for you, then you can use the tuple to iterate over all the template arguments using C++17 fold expressions:
class SomeWeaponWithAttachments: public WeaponWithAttachments<SomeWeapon,SomeAttachment,AnotherAttachment> {
public:
SomeWeaponWithAttachments()
: SomeWeaponWithAttachments{attachment_types} {
return;
}
protected:
template <typename... Attachments>
SomeWeaponWithAttachments(std::tuple<Attachments...> const&) {
(attachments.push_back(std::make_shared<Attachments>()), ...);
return;
}
};
Try it here!
In C++17 you might also add a static assertion with fold expressions into the constructor to make sure that the types actually inherit from BaseAttachment:
static_assert((std::is_base_of_v<BaseAttachment, Attachments> && ...), "Template arguments must inherit from 'BaseAttachment'.");
Assume I have a some classes architecture (the number of the classes is growing up during the development time), that each class inherit from N classes with the same basic interface. What is the best way (if possible) to create a base function (in the base class OR in the derived class) that will iterate over the inheritances?
Target: Avoid developers mistakes and make sure we won't forget to call all the base functions from all of the inheritances & make the code more clear to read and understandable.
Please see edit notes for updated state
Short Example:
class shared_base {
public:
virtual void func() = 0;
}
class base_1 : virtual public shared_base {
public:
void func() override {}
}
class base_2 : virtual public shared_base {
public:
void func() override {}
}
class target : virtual public base_1, virtual public base_2 {
public:
void func() override {
// Instead of:
base_1::func();
base_2::func();
// ... My func() implementation
/*
~~TODO~~
for_each(std::begin(inheritances), std::end(inheritances), [](auto& inheritance) -> void { inheritance::func(); })
~~TODO~~
*/
}
}
More descriptive & practical example:
class base {
public:
virtual void func() = 0;
/*...Some interface (pure virtual) functions...*/
}
class base_core : virtual public base {
public:
void func() override {}
/*...Some base implementations for the rest...*/
protected:
template <typename FuncT>
virtual void iterate_over_base_core_inheritances(FuncT function_to_apply) {
/*~~TODO~~*/
}
}
template <class Decorator = base_core, typename = typename std::enable_if<std::is_base_of<base_core, Decorator>::value>::type>
class core_1 : virtual public Decorator {
public:
void func() override {
// Will iterate (once) over Decorator
/*iterate_over_base_core_inheritances([](core_base*) -> void {
// Implementation
});*/
// Instead of:
Decorator::func();
}
/*More functions implementations*/
}
template <class Decorator = base_core, typename = typename std::enable_if<std::is_base_of<base_core, Decorator>::value>::type>
class core_2 : virtual public core_1<>, virtual public Decorator {
public:
void func() override {
// Will iterate (twice) over core_1 and Decorator
/*iterate_over_base_core_inheritances([](core_base*) -> void {
// Implementation
});*/
// Instead of:
Decorator::func();
core_1::func();
//... Self func() implementation
}
/*More functions implementations*/
protected:
// If it's not possible doing it in the upper hierarchy level is it possible do it here?
template <typename FuncT>
void iterate_over_base_core_inheritances(FuncT function_to_apply) override {
/*~~TODO~~*/
}
}
Some things to know:
I am working on Linux 64x platform (Ubuntu 16.04)- if it's matter for the answers.
The idea behind this code is to create kind of Decorator DP, which will be easy to extend and to understand, and also will enable the developers to use the protected functions/attributes of the base class.
A practical example (for my actual use) can be found in this commit.
Edit:
Thanks to #RaymondChen I got a working solution, with (so far) only one minor issue: Every time I want to use a class that implemented this way, I need to specify the core_base class in it's template arguments list (before- I was using the default type parameter). I am looking for a way to solve this issue.
The current solution:
template <class ...Decorators>
class core_2 : virtual public Decorators... {
public:
static_assert((std::is_base_of<base_core, Decorators>::value && ...), "All decorators must inherit from base_core class.");
void func() override {
(Decorators::func(), ...);
//... Self func() implementation
}
/*More functions implementations*/
}
Creating an instance example:
Current:
std::shared_ptr<base> base = std::make_shared<core_2<core_1<base_core>, core_3<base_core>>>();
Desired:
std::shared_ptr<base> base = std::make_shared<core_2<core_1<>, core_3<>>>();
A practical example (for my actual use) can be found in this commit.
Thanks to #RaymondChen I got really close to my original target with the following solution [See update section at the bottom]:
template <class ...Decorators>
class core_2 : virtual public Decorators... {
public:
static_assert((std::is_base_of<base_core, Decorators>::value && ...), "All decorators must inherit from base_core class.");
void func() override {
(Decorators::func(), ...);
//... Self func() implementation
}
/*More functions implementations*/
}
Explanation:
Using parameters pack we can create a "list" of classes we inherit from, and using folding expression [c++17] we can implement it in just few lines of code.
Pros compare to my original idea:
The object creation line is more clear and logically now:
Before:std::shared_ptr<base> base = std::make_shared<core_2<core_1<core_3<>>>>();
After:std::shared_ptr<base> base = std::make_shared<core_2<core_1<base_core>, core_3<base_core>>>();
Because core_1 & core_3 are independent, but core_2 is using both of them.
No need of new function in the base/derived class, it's just fit within the target line (for example in is_equal function that didn't mention within this post).
Lost functionality:
Template validation of is_base_of (Solved with static_assert & fold expressions).
Default inheritance in case that no inheritance specified is not possible yet (Still trying to solve).
Current:
std::shared_ptr<base> base = std::make_shared<core_2<core_1<base_core>, core_3<base_core>>>();
Desired:
std::shared_ptr<base> base = std::make_shared<core_2<core_1<>, core_3<>>>();
Update
After a lot of research and tries, I came up with the following solution (improved also with C++20 concepts feature):
template <class T>
concept Decorator = std::is_base_of_v<base_core, T>;
class empty_inheritance {};
template<typename Base = base_core, typename ...Decorators>
struct base_if_not_exists {
static constexpr bool value = sizeof...(Decorators);
using type = typename std::conditional<value, empty_inheritance, Base>::type;
};
template <Decorator ...Decorators>
class core_2 : virtual public base_if_not_exists<base_core, Decorators...>::type, virtual public Decorators... {
public:
void func() override {
if constexpr (!base_if_not_exists<base_core, Decorators...>::value) {
base_core::func();
}
(Decorators::func(), ...);
//... Self func() implementation
}
/*More functions implementations*/
}
No functionality lost :)
I have a question regarding a design in C++.
As you see in the code below there is a design problem. I want to be able to have a TestClass which inherits from zero or more classes derived from ModeBase (ModeOne and ModeTwo in this example). If TestClass inherits from ModeOne, it would have the ability to use MethodeOne(), and it would be a requirement for TestClass to implement MethodOne() which is what I want.
class ModeBase
{
//--Methods--------------------------------------------------------------------
public:
virtual ~ModeBase() = default;
};
class ModeOne : private ModeBase
{
//--Methods--------------------------------------------------------------------
public:
virtual ~ModeOne() = default;
virtual void MethodOne() {}
};
class ModeTwo : private ModeBase
{
//--Methods--------------------------------------------------------------------
public:
virtual ~ModeTwo() = default;
virtual void MethodTwo() {}
};
class TestBase
{
//--Methods--------------------------------------------------------------------
public:
TestBase() : currentMode_( nullptr ) {}
virtual ~TestBase() = default;
template <class Mode, class T>
void ChangeMode()
{
if( std::is_base_of<Mode, T>::value )
{
// Class does inherit from Mode so we make sure the current mode
// has changed
currentMode_ = std::make_shared<Mode>();
}
else
{
// Class does not inherit from Mode so we don't do anything
}
}
template <class Mode>
bool CurrentMode()
{
if( std::dynamic_pointer_cast<Mode>(currentMode_) != nullptr )
{
return true;
}
return false;
}
//--Data members---------------------------------------------------------------
private:
std::shared_ptr<ModeBase> currentMode_;
};
class TestOne
: public TestBase
, private ModeOne
, private ModeTwo
{
//--Methods--------------------------------------------------------------------
~TestOne() = default;
void HeartbeatTick()
{
if( CurrentMode<ModeOne>() )
{
MethodOne();
}
else if( CurrentMode<ModeTwo>() )
{
MethodTwo();
}
}
virtual void MethodOne() {}
virtual void MethodTwo() {}
};
class SomeManager
{
~SomeManager() = default;
void ChangeAllMode()
{
for( auto it = vector_.begin(); it != vector_.end(); ++it )
{
// Here is the problem with this implementation. I need to know
// the type of the TestBase derived class (TestOne) to use it as
// a `ChangeMode` method template parameter.
//(*it)->ChangeMode<AIModeFollowLine, SOMETYPE>();
}
};
std::vector<std::shared_ptr<TestBase>> vector_;
};
I already know this is bad design since vector_ will be filled at runtime so I have no way of using ChangeMode like that. It appears that it would be a good solution to use multimethods, wouldn't it ? If so, what would the design look like ?
Multimethods (AKA multiple dispatch) deals with the issue of dispatching a call to a single function based on the runtime type of the parameters involved. This does not appear to be your issue (or have I misunderstood you?), as you have two different method names, implemented on two different types.
Your goal appears to be to select a method implementation based on a runtime type that you have injected into a class. It is not clear whether you are able to dictate the form which that injection takes but if you are then why do you not directly inject the implementation? Then you could use an implicit interface rather than an explicit one. In other words why not inject a functor-like object?
class TestBase
{
public:
typedef std::function<void ()> Ticker;
TestBase(Ticker hbTicker) : ticker{hbTicker} {}
void HeartbeatTick() {
ticker();
}
void setTicker(Ticker hbTicker){
ticker = hbTicker;
}
private:
Ticker ticker;
};
Seems like a lot less complicated to me if that meets your requirements.
If you really do need to implement multiple dispatch you will probably need to implement a visitor pattern on each of the parameters whose runtime type you need to determine. Not sure if that would work for multiple parameters though (I've not tried multiple parameters myself at least). Or you could use RTTI and a case statement or something like that.
I am just being stupid here !
I just have to use a different ChangeMode() method in order to know if TestBase and thus TestOne is of type ModeBase:
template<typename Mode>
bool
IsSame( TestBase* base )
{
return dynamic_cast<Mode*>(base) != nullptr;
};
template <class Mode>
void
ChangeMode()
{
if( isSame<Mode>(this) )
{
// Change the ticker method
}
else
{
}
}
I'm working with a simple object model in which objects can implement interfaces to provide optional functionality. At it's heart, an object has to implement a getInterface method which is given a (unique) interface ID. The method then returns a pointer to an interface - or null, in case the object doesn't implement the requested interface. Here's a code sketch to illustrate this:
struct Interface { };
struct FooInterface : public Interface { enum { Id = 1 }; virtual void doFoo() = 0; };
struct BarInterface : public Interface { enum { Id = 2 }; virtual void doBar() = 0; };
struct YoyoInterface : public Interface { enum { Id = 3 }; virtual void doYoyo() = 0; };
struct Object {
virtual Interface *getInterface( int id ) { return 0; }
};
To make things easier for clients who work in this framework, I'm using a little template which automatically generates the 'getInterface' implementation so that clients just have to implement the actual functions required by the interfaces. The idea is to derive a concrete type from Object as well as all the interfaces and then let getInterface just return pointers to this (casted to the right type). Here's the template and a demo usage:
struct NullType { };
template <class T, class U>
struct TypeList {
typedef T Head;
typedef U Tail;
};
template <class Base, class IfaceList>
class ObjectWithIface :
public ObjectWithIface<Base, typename IfaceList::Tail>,
public IfaceList::Head
{
public:
virtual Interface *getInterface( int id ) {
if ( id == IfaceList::Head::Id ) {
return static_cast<IfaceList::Head *>( this );
}
return ObjectWithIface<Base, IfaceList::Tail>::getInterface( id );
}
};
template <class Base>
class ObjectWithIface<Base, NullType> : public Base
{
public:
virtual Interface *getInterface( int id ) {
return Base::getInterface( id );
}
};
class MyObjectWithFooAndBar : public ObjectWithIface< Object, TypeList<FooInterface, TypeList<BarInterface, NullType> > >
{
public:
// We get the getInterface() implementation for free from ObjectWithIface
virtual void doFoo() { }
virtual void doBar() { }
};
This works quite well, but there are two problems which are ugly:
A blocker for me is that this doesn't work with MSVC6 (which has poor support for templates, but unfortunately I need to support it). MSVC6 yields a C1202 error when compiling this.
A whole range of classes (a linear hierarchy) is generated by the recursive ObjectWithIface template. This is not a problem for me per se, but unfortunately I can't just do a single switch statement to map an interface ID to a pointer in getInterface. Instead, each step in the hierarchy checks for a single interface and then forwards the request to the base class.
Does anybody have suggestions how to improve this situation? Either by fixing the above two problems with the ObjectWithIface template, or by suggesting alternatives which would make the Object/Interface framework easier to use.
dynamic_cast exists within the language to solve this exact problem.
Example usage:
class Interface {
virtual ~Interface() {}
}; // Must have at least one virtual function
class X : public Interface {};
class Y : public Interface {};
void func(Interface* ptr) {
if (Y* yptr = dynamic_cast<Y*>(ptr)) {
// Returns a valid Y* if ptr is a Y, null otherwise
}
if (X* xptr = dynamic_cast<X*>(ptr)) {
// same for X
}
}
dynamic_cast will also seamlessly handle things like multiple and virtual inheritance, which you may well struggle with.
Edit:
You could check COM's QueryInterface for this- they use a similar design with a compiler extension. I've never seen COM code implemented, only used the headers, but you could search for it.
What about something like that ?
struct Interface
{
virtual ~Interface() {}
virtual std::type_info const& type() = 0;
};
template <typename T>
class InterfaceImplementer : public virtual Interface
{
std::type_info const& type() { return typeid(T); }
};
struct FooInterface : InterfaceImplementer<FooInterface>
{
virtual void foo();
};
struct BarInterface : InterfaceImplementer<BarInterface>
{
virtual void bar();
};
struct InterfaceNotFound : std::exception {};
struct Object
{
void addInterface(Interface *i)
{
// Add error handling if interface exists
interfaces.insert(&i->type(), i);
}
template <typename I>
I* queryInterface()
{
typedef std::map<std::type_info const*, Interface*>::iterator Iter;
Iter i = interfaces.find(&typeid(I));
if (i == interfaces.end())
throw InterfaceNotFound();
else return static_cast<I*>(i->second);
}
private:
std::map<std::type_info const*, Interface*> interfaces;
};
You may want something more elaborate than type_info const* if you want to do this across dynamic libraries boundaries. Something like std::string and type_info::name() will work fine (albeit a little slow, but this kind of extreme dispatch will likely need something slow). You can also manufacture numeric IDs, but this is maybe harder to maintain.
Storing hashes of type_infos is another option:
template <typename T>
struct InterfaceImplementer<T>
{
std::string const& type(); // This returns a unique hash
static std::string hash(); // This memoizes a unique hash
};
and use FooInterface::hash() when you add the interface, and the virtual Interface::type() when you query.
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.