ytrembla
10/22/2008 9:26:00 AM
In article <d95ed2b5-6f83-4e38-962f-01cb95914246@h2g2000hsg.googlegroups.com>,
..rhavin grobert <clqrq@yahoo.de> wrote:
>On 21 Okt., 17:55, ".rhavin grobert" <cl...@yahoo.de> wrote:
>> On 21 Okt., 17:14, "Andrew Koenig" <a...@acm.org> wrote:
>>
>> Guess the following:
>>
>> int Obj::Read() const;
>> int Obj::Write(int iWhatever);
>>
>> int PrettyFunction(int iCommand, Obj* pObject, int iAux)
>> {
>> switch(iCommand)
>> {
>> case CMD_READ:
>> return pObject->Read();
>> case CMD_WRITE:
>> return pObject->Write(iAux);
>> default:
>> DropBombOnWhiteHouse();
>> }
>> }
>>
>> If you have a Obj const* it would still be apropriate to call the
>> PrettyFunction with the CMD_WRITE by const_cast'ing.
>
>err, i meant "CMD_READ" and forgot a "return" ;-)
I'd still say: "No it isn't.". You are breaking encapsulation and
breaking the contract given in the interface.
The interface says:
I take a "Obj *", I may modify it. That's the contract.
You say:
I looked at the implementation of PrettyFunction and as it happens in
that particular version of the implementation if I send CMD_READ as
command, it does not actually modify the Obj *, so in spite of what
the contract says, I'll just pass it an actual constant pointer
const_cast'ed away.
I say:
At some point in the future, someone will modify PrettyFunction. He
will be very careful, have unit tests to ensure that the modification
do not break anything compared to the existing behavior as described
in the contract. The new version of PrettyFunction will modify Obj *
even for the CMD_READ command but that is perfectly legal according to
the contract. The code modification will be tested, reviewed and
included in the package. All perfectly sane and proper. Your code
will then break and you will have a great time trying to figure out
why.
Let me put it otherwise:
You have a cashpoint card (ATM for North American). It has your name
and account number on it and it can be used as a proof of ID (as
const), there's a PIN associated to it which make the cashpoint card
non-const since it allows access to the money in your bank account.
class CashPointCard
{
std::string viewName() const;
int viewAccountNumber() const;
int viewPin(); /// non-const
}
What would you say of:
LendCardAndPinToSalesman(CashPointCard * card, int command)
{
switch(command)
{
case VERIFY_ID:
verify(card->viewName);
case PAY:
withrawMoney(card->viewAccountNumber(), card->viewPin);
}
Will you give your card and pin even if you have observed a salesman
once and to verify id they do not look at the pin?
Or would you rather use:
LendCardNoPinAccessToSalesman(CashPointCard const * card, int command)
{
switch(command)
{
case VERIFY_ID:
verify(card->viewName);
// Can't be done as it would break the contract.
// case PAY:
// withrawMoney(card->viewAccountNumber(), card->viewPin);
}
Yannick