child friend

  • Thread starter Mike -- Email Ignored
  • Start date
M

Mike -- Email Ignored

In a base class, I have a state variable to
which I want to allow access by one particular
child class and none other. So I made the
child class a friend to the base class.
OK?

Thanks,
Mike.
 
M

Mike -- Email Ignored

I think what would be better would be better to give or deny inherited
classes that capability. Something like the following:

struct base_class
{
private:
int x;
friend struct NeedsX;
};

struct class_A : public base_class
{
void test() { x = 3; } // Compile error
};

struct NeedsX
{
void setState(base_class &b) { b.x = 3; }
};

// This class can manipulate the base class "state" struct class_B :
public base_class, public NeedsX {
void test() { setState(*this); }
};

Of course, the downside to this is that anyone can
inappropriately inherit NeedsX. A similar criticism
applies to the method that I will probably use to
avoid the design hole:

class Base
{
...
private:
virtual void computeX(int neededForX); // sets x_;
virtual int getX()const; // returns x_
void useX(){...; int x = getX(); ...;}
int x_;
};

class Child : public Base
{
...
private:
virtual void computeX(int neededForX); // sets y_;
virtual int getX()const; // returns y_
int y_;
};

This works because a parent can monitor
private activities of her children. ;)

BTW, can someone guide me to the chapter
and verse that specifies this last point?

Thanks,
Mike.
 
M

Mike -- Email Ignored

Ian said:
Jeff Schwab wrote: [...]
Factory classes and proxy classes are common idiomatic uses.

Sorry, I'm not seeing it. If you or the OP would care to explain
further, I'm guessing we can find a better way than "friendship."
[...]

It is part of the OO objective of obtaining stability by
controlling who can to what. I just googed "factory
class" and found better explanations than I can come up
with. A related but different concept is that of the
"singleton", which you cal also goog. Over the years,
I have made use of both of these.

HTH,
Mike.
 
I

Ian Collins

Jeff said:
Sorry, I'm not seeing it. If you or the OP would care to explain
further, I'm guessing we can find a better way than "friendship."
Have you ever used factories or proxies? Whilst it isn't required that
objects created by factories can only be created by the factory, it is
often desirable. The same applies to a proxy, the only sensible place
to create one is in the operators of the class that return them.

For example, with XML DOM Elements have an owner Document and are
created by that document. Orphan elements are neither required nor
desired. An Element could have a public constructor with a Document
parameter, but that makes the element (product) responsible for
notifying the document (factory) it has been created. It also required
Document to expose the notification method. I'm sure you'd agree this
is arse about face.
 
I

Ian Collins

Jeff said:
Of course.


If you say so, boss.

Is there anywhere else?
No, I would not agree. If I were implementing this sort of
architecture, I would probably (1) make the element's constructor
private, (2) give the element class a static member function that
accepts a document and returns a new element, and (3) make the
document's "element_added" notification function public.

In other words you don't like the factory pattern. That's fair enough.
I was simply providing an illustration of it's use.
The down side,
relative to the friend-based approach, is that the document's public
notification function may be open to abuse, but I don't see that as a
significant problem relative to the flexibility it provides. Given that
the element is coupled to the document, I certainly prefer coupling it
to a document concept or interface, rather than tightly coupling it to a
specific document class (as is done with friendship). Similarly, since
the notification function is public, the document no longer has to know
the specific type of the element.

It really just comes down to where the creator function lives. It can
either be a member of the containing object, or a static member of the
contained object.

I guess it depends whether you prefer to write

Element fred = Element::create( "fred", document );

Or

Element fred = document.createElement("fred");

Or in my case,

Element fred = document.create<Element>("fred");

I frequently use Document as a base class for specialised document
types, so element creation is further simplified to:

Element fred = create<Element>("fred");

rather than

Element fred = Element::create( "fred", *this );
 
M

ma740988

I think what would be better would be better to give or deny inherited
classes that capability. Something like the following:

struct base_class
{
private:
   int x;
   friendstruct NeedsX;

};

struct class_A : public base_class
{
   void test() { x = 3; } // Compile error

};

struct NeedsX
{
   void setState(base_class &b) { b.x = 3; }

};

// This class can manipulate the base class "state"
struct class_B : public base_class, public NeedsX
{
   void test() { setState(*this); }



};- Hide quoted text -

- Show quoted text -

I have a follow on question to this. Consider
class base {
public :
virtual int read ( /* arguments */ ) = 0 ;
virtual int write ( /* arguments */ ) = 0 ;
};

class derived_1 : public base {
public :
int read ( /* arguments */ ) { return whatever ; }
int write( /* arguments */ ) { return whatever ; }
};

class derived_2 : public base {
public :
int read ( /* arguments */ ) { return whatever ; }
int write( /* arguments */ ) { return whatever ; }
};

enum { DER1, DER2, DER_LAST };
// later
typedef std::vector < base* > BASE_VEC ;
BASE_VEC bv ( DER_LAST ) ;
bv [ DER1 ] = new derived_1 ;
bv [ DER2 ] = new derived_2 ;

// now call the read or write methods through the common base
interface.
bv [ DER1 ]->read ( /*whatever*/ ) ;
bv [ DER2 ]->read ( /*whatever*/ ) ;

Now that was yesterday. Today I realized I need to extend derived_2's
_and_ only derived_2's interface. The only way do this while
maintaining a vector of base pointers is to add virtual methods to
Base.

So now:

class base {
public :
virtual int read ( /* arguments */ ) = 0 ;
virtual int write ( /* arguments */ ) = 0 ;

//lots of stuff added here that _only_ derived 2 cares about
virtual void set_pitch_command ( /*arguments*/) { /* do
nothing* / }
virtual int get_pitch_command () const { return 1; /* return
anything*/ }
virtual void set_pitch_reference ( /*arguments*/) { /* do
nothing* / }
virtual int get_pitch_reference () const { return 1; /* return
anything*/ }
};

and of course derived_2 will implement the appopriate functionality.

In my view extending the base class interface with a litany of
functinos that only 1 dervied class cares about just seem wrong and
suggests time for a redesign, however, I'm not sure what the right
approach is here short of abandoning the vector of base pointers.

Thoughts.

Thanks
 
I

Ian Collins

Jeff said:
Yes. It's common to have a proxy on a client machine that represents
some concrete object living on a server. The point of the proxy is to
forward messages to (and responses from) the server. In this case, it
is the client machine's run-time environment, not the concrete object,
that must know how to create the proxy.
OK, I should have been more restrictive in my description. I was
referring to simple proxy classes used to differentiate between reading
and writing array like classes with an operator[].
That's not what I said. In the example you provided, though, I don't
like that the document is doubling as an element-factory.

You'd better take that up with w3c!
 
M

mzdude

I have a follow on question to this.  Consider

Now that was yesterday.  Today I realized I need to extend derived_2's
_and_ only derived_2's interface.  The only way do this while
maintaining a vector of base pointers is to add virtual methods to
Base.

and of course derived_2 will implement the appopriate functionality.

In my view extending the base class interface with a litany of
functinos that only 1 dervied class cares about just seem wrong and
suggests time for a redesign, however, I'm not sure what the right
approach is here short of abandoning the vector of base pointers.

Thoughts.

Yes. Either use the visitor pattern to extend the derrived_2, or your
design needs modification.

It's beginning to sound like the is-a relationship is tenuous at best
given the departure from derrived_1 and derrived_2.
 

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

No members online now.

Forum statistics

Threads
474,164
Messages
2,570,897
Members
47,439
Latest member
shasuze

Latest Threads

Top