Topic: private and really private


Author: Valentin Bonnard <bonnardv@pratique.fr>
Date: 1998/04/29
Raw View
Lo=EFc Tr=E9gan <loic.tregan@isdnet.net> writes:

> I have a bank account, wich may be modified by the bank :

[...]

> my problem is the following : there is the risk that a developper of th=
e
> Bank class use the _value data member instead of SetValue.
> On the other side, it is not possible to remove the friend relationship=
 and
> put SetValue in the public section, since only the bank is allowed to
> modified this account.

In the library I am currently writting (AGIL++, a GUI library, not=20
a banking system), I have used a key:

class Account {
private :
    int    _value;
public :
    int GetValue();
// controled:
    class BankKey
    {
        friend class Bank;
        BankKey () { }
    };
    void   SetValue( int value, BankKey)
};

class Bank {
    vector<Account>    accounts;
....;
};

--=20

Valentin Bonnard                mailto:bonnardv@pratique.fr
info about C++/a propos du C++: http://pages.pratique.fr/~bonnardv/
---
[ comp.std.c++ is moderated.  To submit articles, try just posting with ]
[ your news-reader.  If that fails, use mailto:std-c++@ncar.ucar.edu    ]
[              --- Please see the FAQ before posting. ---               ]
[ FAQ: http://reality.sgi.com/austern_mti/std-c++/faq.html              ]





Author: Marc Girod <girod@stybba.ntc.nokia.com>
Date: 1998/05/02
Raw View
>>>>> "LT" =3D=3D Lo=EFc Tr=E9gan <loic.tregan@isdnet.net> writes:

LT> So for mee the only solution is to have a finer granulosity in friend=
ship
LT> relations, instead of the raw class-scope :

The granularity is as fine as _you_ want it to be. "class" is a
generic concept that _you_ are free to map onto whatever you find
suitable.

In this case, split the Account into an interface and an
implementation, so that the implementation inherits from the
interface:

class Account {
    friend    Bank;
private :
    virtual void SetValue(int) =3D 0;
public :
    virtual int GetValue() const =3D 0;
    virtual ~Account() {}
};

class Account_imp: Account {
// ...
};

Of course, you must change your Bank to store polymorphic references
to accounts (ref counted smart pointers will best do the job), and
build your accounts through a factory.

--=20
Marc Girod                Valimo 1/2         Voice:  +358-9-511 63331
Nokia Telecommunications  P.O. Box 315       Mobile: +358-40-569 7954
NWS/NMS/NMS for Data      00045 NOKIA Group  Fax:    +358-9-511 63310
                          Finland            marc.girod@ntc.nokia.com




                                =20
---
[ comp.std.c++ is moderated.  To submit articles, try just posting with ]
[ your news-reader.  If that fails, use mailto:std-c++@ncar.ucar.edu    ]
[              --- Please see the FAQ before posting. ---               ]
[ FAQ: http://reality.sgi.com/austern_mti/std-c++/faq.html              ]





Author: "Konstantin Baumann" <kostab@uni-muenster.de>
Date: 1998/04/28
Raw View
Lo=EFc Tr=E9gan wrote:

> I have a bank account, wich may be modified by the bank :
>=20
> class Account {
>     friend    Bank;
> private :
>     int    _value;
>     void   SetValue( int value)
> public :
>     int GetValue();
> };
>=20
> class Bank {
>     vector<Account>    accounts;
> ....;
> };
>=20
> my problem is the following : there is the risk that a developper of th=
e
> Bank class use the _value data member instead of SetValue.
> On the other side, it is not possible to remove the friend relationship=
 and
> put SetValue in the public section, since only the bank is allowed to
> modified this account.

What about this:

class Account {
public:
 int getValue() const;

 class Modifier {
  friend Bank;
  void setValue(Account& ac, int value) { ac.setValue(value); }
 };

private:
 friend Modifier;
 void setValue(int value);
 int value_;
};

So, only the bank can modify the value-data of account via:

void Bank::changeValue(Account& ac, int value) {
 typename Account::Modifier AcMod;
 AcMod::setValue(ac, value);
}

Another solution would be:

class Account {
public:
 int getValue() const;

protected:
 void setValue(int value);

private:
 int value_;
};

class SecretAccount : public Account {
protected:
 friend Bank;
 void setValue(int value) { Account::setValue(value); }
};

Then a bank stores a vector of SecretAccount's but exports only Account's=
 to
the public:

class Bank {
public:
 const Account& getAccount(unsigned int i) const { return(accounts_[i]); =
}
 Account& getAccount(unsigned int i) { return(accounts_[i]); }

protected:
 void change(unsigned long i, int value) { accounts_[i].setValue(value); =
}

private:
 vector<SecretAccount> accounts_;
};

--=20
Konstantin Baumann                   Westfaelische Wilhelms-Universitaet=20
Institut fuer Informatik (Zi. 603),  Einsteinstr. 62,   D-48149 Muenster
mailto:kostab@math.uni-muenster.de                  Tel:+49-251-83-32701
http://wwwmath.uni-muenster.de/cs/u/kostab/         Fax:+49-251-83-33755
---
[ comp.std.c++ is moderated.  To submit articles, try just posting with ]
[ your news-reader.  If that fails, use mailto:std-c++@ncar.ucar.edu    ]
[              --- Please see the FAQ before posting. ---               ]
[ FAQ: http://reality.sgi.com/austern_mti/std-c++/faq.html              ]





Author: Christopher Eltschka <celtschk@physik.tu-muenchen.de>
Date: 1998/04/28
Raw View
Lo=EFc Tr=E9gan wrote:
>=20
> I have a bank account, wich may be modified by the bank :
>=20
> class Account {
>     friend    Bank;
> private :
>     int    _value;
>     void   SetValue( int value)
> public :
>     int GetValue();
> };
>=20
> class Bank {
>     vector<Account>    accounts;
> ....;
> };
>=20
> my problem is the following : there is the risk that a developper of th=
e
> Bank class use the _value data member instead of SetValue.
> On the other side, it is not possible to remove the friend relationship=
 and
> put SetValue in the public section, since only the bank is allowed to
> modified this account.

What about this:

class Account
{
  friend Bank
  class // really private
  {
    friend Account;
    int value;
  } members;
  void SetValue(int value);
public:
  int GetValue();
};

class Bank
{
  vector<Account> accounts;
  ...
}

Since friendship is not transitive (the friends of my friends are
not automatically my friends), only Account members have access to
the members of members. This has no overhead to using them direct
(except maybe in compiling time to parse the extra "members." on
each access to member variables), and allows easy change to the
pimple idiom later if you decide that it would be useful.

The access to those variables is only minimally different to
normal access:

void Account::GetValue()
{
  return members.value;
}

Note that this "members." actually acts as a prefix, so there's
no reason to use such a prefix on the single member variables.
(If you replace members by a simple m, the syntax m.value doesn't
look much different to the often used naming m_value.)
---
[ comp.std.c++ is moderated.  To submit articles, try just posting with ]
[ your news-reader.  If that fails, use mailto:std-c++@ncar.ucar.edu    ]
[              --- Please see the FAQ before posting. ---               ]
[ FAQ: http://reality.sgi.com/austern_mti/std-c++/faq.html              ]





Author: "Lo c Tr gan" <loic.tregan@isdnet.net>
Date: 1998/04/23
Raw View
I have a bank account, wich may be modified by the bank :

class Account {
    friend    Bank;
private :
    int    _value;
    void   SetValue( int value)
public :
    int GetValue();
};

class Bank {
    vector<Account>    accounts;
....;
};

my problem is the following : there is the risk that a developper of the
Bank class use the _value data member instead of SetValue.
On the other side, it is not possible to remove the friend relationship and
put SetValue in the public section, since only the bank is allowed to
modified this account.

So for mee the only solution is to have a finer granulosity in friendship
relations, instead of the raw class-scope :

class Account {
private :
    int    _value;
    friend Bank void   SetValue( int value);
public :
    int GetValue();
};

or

class Account {
private :
    int    _value;
    friend Bank, X, Y {
        void   SetValue( int value);
    }
public :
    int GetValue();
};

or ( i really like this last one ) :

class Account {
private :
    int    _value;
Bank, X, Y :
     void   SetValue( int value);
public :
    int GetValue();
};



this concept can be extended to the interface :

class CheckAccount : public( Bank) SecretInfo
{
}
ie : CheckAccount is a kind of SecretInfo only for the Bank; That's what
happen in th real life : some services are accessible only form some other
specific services.

more over, a class is a lots of thing : a strucutre (a container), a
mini-namespace, a security policy ( private, public, protected).
So in the same way that a class scope may be interpreted as a little
namespace (see my previous message where i wanted a "using class X" like
"using namespace Y" for coherency reason), in the other sens (from classes
to namespaces) maybe the private/protected/public clauses ans friend
relationship may be extended to namespaces.

I think such extension does not complicate the language, but in opposite
make it simpler because it makes the language more coherent, all what the
user learn on namespaces can be uses for classes and vice-versa. More over,
it has a pragmatic utility, enabling to provide safer code.



[ comp.std.c++ is moderated.  To submit articles, try just posting with ]
[ your news-reader.  If that fails, use mailto:std-c++@ncar.ucar.edu    ]
[              --- Please see the FAQ before posting. ---               ]
[ FAQ: http://reality.sgi.com/austern_mti/std-c++/faq.html              ]