Virtualization of a 'protected interface'

M

Marcel Müller

I have an abstract base class that provides public and protected pure
functions.

class MyBase
{protected:
virtual void InternalService() = 0;

public:
virtual void PublicService() = 0;

void CommonImplementation()
{ // Do something that depends on InternalService...
InternalService();
}
};

class MyImplementation : public MyBase
{protected:
void InternalService();

public:
void PublicService();
};

class MyProxy : public MyBase
{private:
MyBase& Backend;

protected:
void InternalService()
{ // Modify Backend.InternalService somehow...
Backend.InternalService(); // <-- access denied
}

public:
MyProxy(MyBase& backend) : Backend(backend) {}

void PublicService()
{ // Modify Backend.PublicService somehow...
Backend.PublicService();
}
};


Unfortunately MyProxy cannot access the protected members of /another/
MyBase instance. Is there another way to do something like that, except
for making MyBase::InternalService public?

The idea behind that is, that references to MyBase objects (MyProxy) can
override some properties of the underlying instance and different
references may override different properties. The common implementation
part in MyBase contains a framework to deal with change notifications
and asynchronously requested informations. If MyProxy overrides a
property it must also intercept the methods to obtain that information.
But these Methods should only be called by the framework in MyBase and
by proxy classes.


Marcel
 
M

Michael Doubez

I have an abstract base class that provides public and protected pure
functions.

class MyBase
{protected:
virtual void InternalService() = 0;

public:
virtual void PublicService() = 0;

void CommonImplementation()
{ // Do something that depends on InternalService...
InternalService();
}

};

class MyImplementation : public MyBase
{protected:
void InternalService();

public:
void PublicService();

};

class MyProxy : public MyBase
{private:
MyBase& Backend;

protected:
void InternalService()
{ // Modify Backend.InternalService somehow...
Backend.InternalService(); // <-- access denied
}

public:
MyProxy(MyBase& backend) : Backend(backend) {}

void PublicService()
{ // Modify Backend.PublicService somehow...
Backend.PublicService();
}

};

Unfortunately MyProxy cannot access the protected members of /another/
MyBase instance. Is there another way to do something like that, except
for making MyBase::InternalService public?

The idea behind that is, that references to MyBase objects (MyProxy) can
override some properties of the underlying instance and different
references may override different properties. The common implementation
part in MyBase contains a framework to deal with change notifications
and asynchronously requested informations. If MyProxy overrides a
property it must also intercept the methods to obtain that information.
But these Methods should only be called by the framework in MyBase and
by proxy classes.

An ugly way to do it is to add a static member function in MyBase that
calls InternalService on its parameter:

class MyBase
{
protected:
//...
static void DoInternalService(MyBase& b)
{
b.InternalService();
}
//...
};

And use it in MyImplementation:
protected:
void InternalService()
{
DoInternalService(Backend);
}

Note that this kind of design if brittle and it breaks encapsulation.

You can also use a static function to return the pointer on the member
function and use it to call InternalService.
 
T

tristan

I am afraid you misunderstand the meaning of proxy.
Proxy is only a representative for a real class entity, or it could be
responsible for some POST-DO / AFTER-DO operations.

InternalService() is protected, that indicates it is available for
MyBase inheritance hierarchy, but Proxy shouldn't be within that hierarchy.

So this design is irrational. At least, MyProxy shouldn't inherit from
MyBase.



Michael Doubez :
 
M

Michael Doubez

I am afraid you misunderstand the meaning of proxy.
Proxy is only a representative for a real class entity, or it could be
responsible for some POST-DO / AFTER-DO operations.

And ?

Still it does break encapsulation.
InternalService() is protected, that indicates it is available for
MyBase inheritance hierarchy, but Proxy shouldn't be within that hierarchy.

In your post, MyProxy inherits from MyBase.
So this design is irrational. At least, MyProxy shouldn't inherit from
MyBase.


In that case, create an internal class in Proxy with a static method
that invoke MyBase::DoInternalService().

class MyProxy
{private:
struct BreakMyBaseEncaps: MyBase
{
static void do_it(MyBase& b)
{
DoInternalService(b);
}
};
//...
void InternalService()
{
BreakMyBaseEncaps::do_it(Backend);
}
//...
};

PS: don't top post
 
M

Marcel Müller

tristan said:
I am afraid you misunderstand the meaning of proxy.
Proxy is only a representative for a real class entity, or it could be
responsible for some POST-DO / AFTER-DO operations.

OK, I should have called it decorator. However, the problem stays the same.

InternalService() is protected, that indicates it is available for
MyBase inheritance hierarchy, but Proxy shouldn't be within that hierarchy.

So this design is irrational. At least, MyProxy shouldn't inherit from
MyBase.

Of course I could split MyBase into an interface with public methods
only and an abstract base with some common implementations. But I still
have the same problem with the abstract base. The abstract base is
incomplete and need help from the derived class to complete the
implementation. Looking at the specification I need to virtualize this
implementation for the decorator to work.

But since N decorator instances can references the same MyImplementation
I cannot use inheritance and simply overload the methods. This would
lead to independent copies of MyImplementation in memory. Besides being
wasting of memory these instances may become inconsistent, and this
breaks the data model.


Marcel
 
M

Marcel Müller

Michael said:
An ugly way to do it is to add a static member function in MyBase that
calls InternalService on its parameter:

class MyBase
{
protected:
//...
static void DoInternalService(MyBase& b)
{
b.InternalService();
}
//...
};

Hmm, this it is not only ugly but also seems to be the only solution
without a significant overhead. I would say it is OK to me. The nice
part is that it does not mess the public interface. I think I will go
that way.

And use it in MyImplementation:
protected:
void InternalService()
{
DoInternalService(Backend);
}

Note that this kind of design if brittle and it breaks encapsulation.


Well, there is almost no application out there that does not break any
design rule. :-/
As long as the ugly parts are safely encapsulated, it will not be the
source of many maintenance problems. I did really more ugly core logic
in this application. First of all the virtualization of an C-style
plug-in interface that required me to infer an object instance from a
callback function's address. But I have a type safe template wrapper
that transforms a member functions pointers and an object instance into
a static function pointer with the same signature. This really dirty and
non portable hack have not been the source of any problem in the last years.


Thanks,

Marcel
 

Ask a Question

Want to reply to this thread or ask your own question?

You'll need to choose a username for the site, which only take a couple of moments. After that, you can post your question and our members will help you out.

Ask a Question

Members online

Forum statistics

Threads
473,769
Messages
2,569,580
Members
45,055
Latest member
SlimSparkKetoACVReview

Latest Threads

Top