Velocity Reviews - Computer Hardware Reviews

Velocity Reviews > Newsgroups > Programming > C++ > An kind of member function name scope specification

Reply
Thread Tools

An kind of member function name scope specification

 
 
Stefan Ram
Guest
Posts: n/a
 
      04-26-2009
For teaching purposes, I wrote this program as a first
example of a definition of a class with non-static functions:

#include <iostream>
#include <ostream>

class Account
{ private:
double balance_;
public:
Account( double const balance );
double balance(); };

::Account::Account( double const balance )
{ this->balance_ = balance; }

double ::Account::balance()
{ return this->balance_; }

int main()
{ Account acct( 100 );
::std::cout << acct.::Account::balance() << '\n';
::std::cout << acct.balance() << '\n'; }

(End of program.)

Regarding »acct.::Account::balance()«:

I was not aware that such a full qualification of a member
function in a member function call was possible at all.

When would one need this? (To call an overloaded function
of a base class?)

Can the above definition of the class still be improved somehow?

~~

Is such an account class is a good example for teaching?

I need the first example to be very simple, yet it needs
to suggest to be useful and related to applications of
the language.

Are there any other good examples of classes, that are

- small and simple
- not already part of the standard library
- not requiring special knowledge of a field
- looking somewhat natural and useful

?

Account classes are used often.

Sometimes, a class for complex numbers is used in teaching,
but such a class already is defined in the standard library
and might look too »mathematical«.

The only other topic that comes to my mind right now
would be a class for a compound date (YYYY, MM, DD)
or time (HH, MM) object.

 
Reply With Quote
 
 
 
 
Stefan Ram
Guest
Posts: n/a
 
      04-26-2009
http://www.velocityreviews.com/forums/(E-Mail Removed)-berlin.de (Stefan Ram) writes:
>::Account::Account( double const balance )
>Can the above definition of the class still be improved somehow?


Except for using a member initialization list,
which I intentionally omitted in this first example.

 
Reply With Quote
 
 
 
 
Ian Collins
Guest
Posts: n/a
 
      04-26-2009
Stefan Ram wrote:
> For teaching purposes, I wrote this program as a first
> example of a definition of a class with non-static functions:
>
> #include <iostream>
> #include <ostream>
>
> class Account
> { private:
> double balance_;
> public:
> Account( double const balance );
> double balance(); };
>
> ::Account::Account( double const balance )
> { this->balance_ = balance; }
>
> double ::Account::balance()
> { return this->balance_; }
>
> int main()
> { Account acct( 100 );
> ::std::cout << acct.::Account::balance() << '\n';
> ::std::cout << acct.balance() << '\n'; }
>
> (End of program.)
>
> Regarding »acct.::Account::balance()«:
>
> I was not aware that such a full qualification of a member
> function in a member function call was possible at all.
>
> When would one need this? (To call an overloaded function
> of a base class?)


Yes, try adding

struct Base
{
double balance() { return 42; }
};

class Account : public Base

and

std::cout << acct.::Base::balance() << '\n';

> Can the above definition of the class still be improved somehow?


You can do away with the superfluous leading :: (::std:.

I assume the layout was to compress the code for Usenet?

The this-> in balance() is superfluous, as is the leading ::.

balance() should be declared cost if it doesn't change anything.

No too big a deal here, but in general geters are a design smell.

--
Ian Collins
 
Reply With Quote
 
Stefan Ram
Guest
Posts: n/a
 
      04-26-2009
Ian Collins <(E-Mail Removed)> writes:
>> #include <iostream>
>> #include <ostream>
>>
>> class Account
>> { private:
>> double balance_;
>> public:
>> Account( double const balance );
>> double balance(); };
>>
>> ::Account::Account( double const balance )
>> { this->balance_ = balance; }
>>
>> double ::Account::balance()
>> { return this->balance_; }
>>
>> int main()
>> { Account acct( 100 );
>> ::std::cout << acct.::Account::balance() << '\n';
>> ::std::cout << acct.balance() << '\n'; }
>>

>I assume the layout was to compress the code for Usenet?


The above layout contains 4 blank lines,
separating the 5 major parts of the source:

- include directives
- a class specifier
- a member function definition
- another member function definition and
- a function definition

If I would add additional empty lines within
each of these parts, those 4 top-most separators
would not stand out in the prominent way the do now.

So this is some kind of global scope view.

If I would show only the class specifier, I might
have used vertical spacing for this, maybe like:

class Account
{
private:
double balance_;

public:
Account( double const balance );
double balance(); };

So, maybe I do not consider formatting to be static, but to be
dynamic. The format used by me in the OP was focused on the
large-scale structure of the source code. If I would have to
edit a function definition, I might start by »unpacking« it,
that is, by inserting some vertical space to see more of the
smaller-scale structure. I assume that readers will adapt the
layout to their current need. I do not deem the layout chosen
by me to be best for all purposes.

 
Reply With Quote
 
Stefan Ram
Guest
Posts: n/a
 
      04-26-2009
Ian Collins <(E-Mail Removed)> writes:
>>public:
>>Account( double const balance );
>>double balance(); };

>No too big a deal here, but in general geters are a design smell.


Yes, but I do not see a getter here. Let me explain why:

I have quoted the public interface of the class above.

It misses an important feature: documentation.

So I will add that document now in the way the names suggest:

- The constructor initializes a new account with
an opening balance as the argument.

- The function »balance« returns the current balance
of the account.

No mentioning of private fields in the documentation.

So a client/caller/reader of this interface can not know
whether this function returns the value of a private field or
obtains the balance using some other means. He does not know
which fields an object of this class has. Therefore, I do not
deem »balance« to be a getter, just a non-void function.

I would see a getter, if the documentation would read instead:

- Each object of this class has a field named »balance_«.
The function »balance« returns the value of this field.

(Admittedly, my code does not have documentation, so both
interpretations are possible. But the first one was intended.)

 
Reply With Quote
 
Ian Collins
Guest
Posts: n/a
 
      04-26-2009
Stefan Ram wrote:
> Ian Collins <(E-Mail Removed)> writes:
>>> public:
>>> Account( double const balance );
>>> double balance(); };

>> No too big a deal here, but in general geters are a design smell.

>
> Yes, but I do not see a getter here. Let me explain why:
>
> I have quoted the public interface of the class above.
>
> It misses an important feature: documentation.
>
> So I will add that document now in the way the names suggest:
>
> - The constructor initializes a new account with
> an opening balance as the argument.
>
> - The function »balance« returns the current balance
> of the account.
>
> No mentioning of private fields in the documentation.
>
> So a client/caller/reader of this interface can not know
> whether this function returns the value of a private field or
> obtains the balance using some other means. He does not know
> which fields an object of this class has. Therefore, I do not
> deem »balance« to be a getter, just a non-void function.


In that case, call it something like calculateBalance.

--
Ian Collins
 
Reply With Quote
 
Stefan Ram
Guest
Posts: n/a
 
      04-26-2009
Ian Collins <(E-Mail Removed)> writes:
>In that case, call it something like calculateBalance.


I deem that to be ugly. I still follow the advice Rob Pike
gave 20 years ago:

»Procedure names should reflect what they do;
function names should reflect what they return.«

Rob Pike; »Notes on Programming in C«; February 21, 1989

http://www.lysator.liu.se/c/pikestyle.html

Also, this is consistent with ISO/IEC 14882:2003(E), where in
<cmath>, the function is named »::std::sin«, not »::std::calculateSin«.

Also, either »calculate« has no meaning at all, or
»calculateBalance« is /more/ transparent than »balance«,
because it leaks the implementation detail that the result of
this call is »calculated« - while »balance« alone is
completely opaque, yielding no information whatsoever about
the implementation, just stating what is returned.
And exposing implementation details is exactly why getters
are being criticized.

 
Reply With Quote
 
Ian Collins
Guest
Posts: n/a
 
      04-27-2009
Stefan Ram wrote:
> Ian Collins <(E-Mail Removed)> writes:
>> In that case, call it something like calculateBalance.

>
> I deem that to be ugly. I still follow the advice Rob Pike
> gave 20 years ago:
>
> »Procedure names should reflect what they do;
> function names should reflect what they return.«
>

In the context of C++, what is a function and what is a procedure?

--
Ian Collins
 
Reply With Quote
 
Stefan Ram
Guest
Posts: n/a
 
      04-27-2009
Ian Collins <(E-Mail Removed)> writes:
>>»Procedure names should reflect what they do;
>>function names should reflect what they return.«

>In the context of C++, what is a function and what is a procedure?


Rob Pike wrote this in the context of C, where it might be
asked as well.

I assume that the terms stem from the Pascal culture.

A Pascal procedure corresponds to a function not returning a
value in C or C++.

A Pascal function corresponds to a function returning a value
in C or C++.

There are functions, like »fopen« that return a value, but are
still named for what they do. This expresses that the main
purpose is deemed to be the action and the value is a
secondary purpose (serving the main purpose by giving a
feedback about the success of the attempted action).

There are functions, like »rand« that have an effect, but
still are named for what they return, because their result is
deemed to be their main purpose, while their effect is deemed
a secondary purpose. (The effect of »rand« is to advance the
random number generator to the next state.)

Naming is especially easy, when a function either only has an
effect or only has a value. In the case of »fopen«, this
separation can be done using OOP as follows:

{ FileOpenAttempt fileOpenAttempt( "source.txt", "r" );
fileOpenAttempt.run();
if( fileOpenAttempt.suceeded() )
{ FILE * file = fileOpenAttempt.result();
use( file );
file.close(); }
else
{ ::std::cerr << fileOpenAttempt.report() << '\n'; }}

Here, »run« is a pure action, while the other element
functions only return a value, but do no action. This is akin
to the structure of natural language, where phrases either
express actions (verbal phrases) or things (noun phrases), but
never both. Insofar, »if( fopen( ... ))« is somewhat
unnatural, but one can get used to it.

 
Reply With Quote
 
James Kanze
Guest
Posts: n/a
 
      04-27-2009
On Apr 27, 1:08 am, (E-Mail Removed)-berlin.de (Stefan Ram) wrote:
> Ian Collins <(E-Mail Removed)> writes:
> >>public:
> >>Account( double const balance );
> >>double balance(); };

> >No too big a deal here, but in general geters are a design
> >smell.


> Yes, but I do not see a getter here. Let me explain why:


> I have quoted the public interface of the class above.


> It misses an important feature: documentation.


> So I will add that document now in the way the names
> suggest:


> - The constructor initializes a new account with
> an opening balance as the argument.


> - The function »balance« returns the current balance
> of the account.


> No mentioning of private fields in the documentation.


> So a client/caller/reader of this interface can not know
> whether this function returns the value of a private field
> or obtains the balance using some other means. He does not
> know which fields an object of this class has. Therefore, I
> do not deem »balance« to be a getter, just a non-void
> function.


I wonder if both you and Ian aren't confusing design level and
implementation level a bit. From a design level, an Account
certainly "hasA" balance (or currentBalance, or whatever), and
that balance is a value, not a behavior. At the design level,
some classes really are just glorified data containers, some are
pure behavior, and some are a mixture of the two (although I
find the latter occur fairly rarely). At the design level, I
can't find anything to say against a class Account which
contains a function balance() (or getBalance(), depending on the
coding guidelines---but I prefer balance(), because it is
logically an attribute).

At the implementation level, of course, whether the class has a
private member, which the function simply returns, or does
something else, is irrelevant. (We use the function, rather
than a public data member, precisely to keep it irrelevant.)

> I would see a getter, if the documentation would read
> instead:


> - Each object of this class has a field named »balance_«.
> The function »balance« returns the value of this field.


Which is, precisely, an example of confounding an implementation
detail and a design aspect (in this case, the contract). The
class has an attribute balance. It may be implemented by a
single private variable, or not. But that's none of the client
code's business.

--
James Kanze (GABI Software) email:(E-Mail Removed)
Conseils en informatique orientée objet/
Beratung in objektorientierter Datenverarbeitung
9 place Sémard, 78210 St.-Cyr-l'École, France, +33 (0)1 30 23 00 34
 
Reply With Quote
 
 
 
Reply

Thread Tools

Posting Rules
You may not post new threads
You may not post replies
You may not post attachments
You may not edit your posts

BB code is On
Smilies are On
[IMG] code is On
HTML code is Off
Trackbacks are On
Pingbacks are On
Refbacks are Off


Similar Threads
Thread Thread Starter Forum Replies Last Post
Having trouble understanding function scope and variable scope Andrew Falanga Javascript 2 11-22-2008 09:23 PM
scope of $name in: (my $name = 123) && something-involving-$name; Yakov Perl Misc 1 11-12-2006 10:05 AM
Function pointer member variable to non-member function Alex C++ 0 10-15-2003 05:26 PM
Function pointer member variable to non-member function slide_o_mix C++ 0 10-15-2003 03:37 PM
Passing a pointer to member function as a parameter to another member function Newsgroup - Ann C++ 5 07-30-2003 02:54 AM



Advertisments