simple class

N

nvangogh

Hi,
I am reading c++ primer.

Exercise 7.4:
Write a class named person that represents the name and address of a
person. Use a string to hold each of these elements. Subsequent
exercises will incrementally add features to this class.

Exercise 7.5:
Provide operations in your person class to return the name and address.
Should these functions be const? Explain your choice.

So I have completed exercise 7.5 in this way:

// a class named person with operations

#include <string>

class Person
{
std::string name() const { return first_name;}
std::string addr() const { return address;}

// data members
std::string first_name;
std::string address;
};

Is this correct?
 
N

nvangogh

Hi,
I am reading c++ primer.

Exercise 7.4:
Write a class named person that represents the name and address of a
person. Use a string to hold each of these elements. Subsequent
exercises will incrementally add features to this class.

Exercise 7.5:
Provide operations in your person class to return the name and address.
Should these functions be const? Explain your choice.

So I have completed exercise 7.5 in this way:

// a class named person with operations

#include <string>

class Person
{
std::string name() const { return first_name;}
std::string addr() const { return address;}

// data members
std::string first_name;
std::string address;
};

Is this correct?
Also what would the constructors for this class look like?
 
V

Victor Bazarov

Also what would the constructors for this class look like?

Consider "Subsequent exercises will incrementally add features...", and
you might find out [later] how the class is to be used, which will
suggest the interface for constructing objects of that class.

The common approach is to provide a constructor that takes two
arguments, each a ref to a const std::string, from which the respective
data member shall be constructed.

*Similar* to a point in two dimensions:

class Point {
...
Point(double x, double y) : mem_x(x), mem_y(y) {}
...
};

(note that the Point c-tor's args are passed by value).

V
 
O

Osmium

nvangogh said:
I am reading c++ primer.

Exercise 7.4:
Write a class named person that represents the name and address of a
person. Use a string to hold each of these elements. Subsequent exercises
will incrementally add features to this class.

Exercise 7.5:
Provide operations in your person class to return the name and address.
Should these functions be const? Explain your choice.

So I have completed exercise 7.5 in this way:

// a class named person with operations

#include <string>

class Person
{
std::string name() const { return first_name;}
std::string addr() const { return address;}

// data members
std::string first_name;
std::string address;
};

Is this correct?

I don't think so. The intent was to have the functions be public, the data
be private. The default is private so an "outsider" can not use the
functions.

As to the first name - I would use the full name. You might want to skim
ahead and see where the author is going with this. First name sounds almost
useless.

Note that "c++ primer" does not identify a book, you need the author's name
too.
 
V

Victor Bazarov

I would do something like this:

class Person
{
public:
std::string get_name() const { return name; }

... { return name_; }
std::string get_addres() const { return address; }

... { return address_; }

;-)
private:
// data members
std::string name_;
std::string address_;

Then, and I think this will be the subsequent exercises, I would provide
a constructor and setters:

public:
Person(const std::string &n, const std::string &a)
: address_(a), name_(n)
{
}
void set_name(const std::string &n) { name_ = n; }
void set_addres(const std::string &a) { address_ = a; }
}

M4

V
 
S

Stefan Ram

nvangogh said:
Write a class named person that represents the name and address of a
person. Use a string to hold each of these elements. Subsequent
exercises will incrementally add features to this class.

This is asking for static fields. Otherwise, the wording would
have to be:

»Write a class named person /whose instances/ represent
the name and address ...«.

It is a common error of beginners not to properly
distinguish between classes and objects.
Provide operations in your person class to return the name and address.

What's an »operation«? Are there any differences to »function«?
 
O

Osmium

Stefan Ram said:
This is asking for static fields. Otherwise, the wording would
have to be:

»Write a class named person /whose instances/ represent
the name and address ...«.

It is a common error of beginners not to properly
distinguish between classes and objects.


What's an »operation«? Are there any differences to »function«?

The book author sounds like one of those nasty real world people. Probably
has germs too ...
 
S

Seungbeom Kim

// a class named person with operations

#include <string>

class Person
{
std::string name() const { return first_name;}
std::string addr() const { return address;}

// data members
std::string first_name;
std::string address;
};

I understand that the exercise was to write something similar to this,
and that features will be added later, but I cannot help wondering
what this class, which has a data member and an inspector function
(and will probably also need a setter function) for each "property",
buys over a simple struct:

struct Person
{
std::string name;
std::string address;
};

I see so many examples like this which I think are stupid, and I
believe examples should be more realistic and interesting in terms
of using language features for solving actual problems (e.g. using
encapsulation facilities to enforce class invariants), not just
for the sake of using the features.
 
J

Jorgen Grahn

This is asking for static fields. Otherwise, the wording would
have to be:

»Write a class named person /whose instances/ represent
the name and address ...«.

That's way too pedantic, IMO. The class exists so we can talk about
these hundreds or millions of person objects as a group, and then it
seems wasteful to pretend we can't talk about the class -- only about
the set of instances of the class. The set of instances /is/ the
class.

I'm pleasantly surprised that the exercise uses the word "represents",
i.e. starts by outlining the /meaning/ of the class. It's not obvious
that a "person" is a name and address rather than a SSN and shoe size
number, or 46 cromosomes, or whatever.
It is a common error of beginners not to properly
distinguish between classes and objects.

I'm often annoyed and/or confused when people mix up that terminology
(e.g. say "class" but really talk about a specific object) but this is
not one of those cases.

/Jorgen
 
W

Wouter van Ooijen

Jorgen Grahn schreef op 10-May-14 2:52 PM:
That's way too pedantic, IMO. The class exists so we can talk about
these hundreds or millions of person objects as a group, and then it
seems wasteful to pretend we can't talk about the class -- only about
the set of instances of the class. The set of instances /is/ the
class.

I totally agree. Some common sense is always required to read a text.

On the other hand... I use a programming style where (templatized)
classes are used to create (compile time) polymorphism. (No objects are
ever created.) Is there a short way to express this? "this class
represents a serial channel" could easily be misinterpred as "an
instance of this class ... ".

Wouter van Ooijen
 
S

Stefan Ram

Wouter van Ooijen said:
On the other hand... I use a programming style where (templatized)
classes are used to create (compile time) polymorphism. (No objects are
ever created.) Is there a short way to express this? "this class
represents a serial channel" could easily be misinterpred as "an
instance of this class ... ".

In C++, the word »class« can never be interpreted as meaning
»an instance of a class« by any reader sane in his mind.

With the first iconsistent use of terminology, the chain is
forged. The first speech crippled...the first thought
mangled...the first expression denied - chains us all,
irrevocably.
 
S

Stefan Ram

David Harmon said:
On 10 May 2014 15:30:14 GMT in comp.lang.c++, (e-mail address removed)-berlin.de
(Stefan Ram) wrote,
In my more lucid moments I might like to agree with you;
nevertheless, that train has left the station. It was already gone
when people were talking about passing structs to functions.

In N3797, the word »struct« is used rarely in the English
text, at one place »a struct type« is used. But, in the case
of C++, what is most important is given in an appendix of
N3797 (C1.2 3.3): »a struct is a class«.

So, when someone speaks of »passing structs to functions«,
this reminds me more of C than of C++. N1570 takes care to
use the terms »structure type« and »structure object«
instead of just »struct«.

In colloquial speech some people indeed omit determinata,
they say »My Internet is slow.« instead of »My Internet
/connection/ is slow.« But when teaching to beginners and
writing assignments, it is more safe to err on the side of
clearness.
 
S

Stefan Ram

In colloquial speech some people indeed omit determinata,

Speech wants to be efficient. So when an isolated word is
ambiguous, this can still be healed by context.

When one says: »I am passing this struct to the function.«,
does he mean »structure type« or »structure object«?
A structure type cannot be passed to a function, so we can
safely conclude that he must mean »structure object«.
Thus, while »struct« is ambiguous in isolation, it is not
ambiguous in the context just given.

But now let's have a look at

|Write a class named person that represents the name and
|address of a person.

. Is »class« »class type« or »class instance« here? In this
case, both interpretations are possible. For example, we
already know the class »::string« that represents
information about the implementation used by providing us
with /static/ fields such as »::string::npos«. Therefore, in
this case, the context does not help to resolve the
ambiguity.

Also, one noun in a phrase cannot mean both »class« and
»class instance« at the same time. The author writes

|class named person

. Here, he does not seem to want to say that a class
/instance/ should be named »person«, but the class itself
should be named »person«. Thus, by the use of this noun
phrase, the meaning of the word »class« in this sentence is
already determined by context and it cannot be read to have
another meaning later.
 
S

Stefan Ram

David Harmon said:
if it can only mean "class type" when context makes it pretty
evident that he intends "class instance".

So, you read

|Write a class named person

as

|Write a class instance named person

?
 
O

Osmium

Stefan Ram said:
But when teaching to beginners and
writing assignments, it is more safe to err on the side of
clearness.

It is always more better to write with a lot of clearness.
 
S

Stefan Ram

Vir Campestris said:
One of the nice things about accessors, not just publicising the data,
is that you are hiding the implementation.

I doubt this.

Say, we have a bank account with an interface:

public: double getBalance();

and a field:

private: double balance;

. Then, problems with »double« are observed, and the
programmer of the account class is asked to change this.
His first change is:

private: ::example::library::fixeddecimal balance;

. But the problems with double values are still being
observed, because the interface still is:

public: double getBalance();

. So eventually, he is forced to change the interface too:

public: ::example::library::fixeddecimal getBalance();

. Now, where is the hiding of the implementation?
 
O

Osmium

Seungbeom Kim said:
I understand that the exercise was to write something similar to this,
and that features will be added later, but I cannot help wondering
what this class, which has a data member and an inspector function
(and will probably also need a setter function) for each "property",
buys over a simple struct:

struct Person
{
std::string name;
std::string address;
};

I see so many examples like this which I think are stupid, and I
believe examples should be more realistic and interesting in terms
of using language features for solving actual problems (e.g. using
encapsulation facilities to enforce class invariants), not just
for the sake of using the features.

I agree, it would be nice to have more appealing examples but I have yet to
see an example that was simple enough for a student and at the same time
meaningful. Some things just have to be bought on faith.

For those with some programming background but new to C++ I feel there is a
sense of security when debugging. The constant thought in the back of your
mind that someone (perhaps your own code) is munging your data. The chances
of accidental munging in C++ are pretty remote; this means you can focus on
the problem at hand.
 
S

Stefan Ram

Paavo Helde said:
Err, no. If the ultimate goal is to keep interfaces fixed, then
getBalance() would still return double for back-compatibility (and marked
deprecated in the documentation and/or by the relevant compiler-specific
extensions) and there would be a new function getBalanceEx() returning a
fixed decimal.

But the effect is the same: all clients that want to benefit
from the new implementation have to be changed. I used to
believe that the promise of encapsulation was that the
implementation can be changed without the clients having to
be changed.
 
J

Jorgen Grahn

One of the nice things about accessors, not just publicising the data,
is that you are hiding the implementation.

Imagine that I've decided to compress the data. Everyone whose name is
Wong will be described by having an ID of 1, everybody whose name is
Smith by 2, and so on.

If you've publicised the data you can't do this. If you've publicised a
method returning a const reference to the string you can.

That's the traditional argument for set/get functions.

But let's face it: in 99 cases out of 100 you're in control over the
client code. Then if you can no longer expose the member, you just
make it private, implement get() and fix up the calling code (which
now fails to compile).

/Jorgen
 
J

Jorgen Grahn

: ....

I agree, it would be nice to have more appealing examples but I have yet to
see an example that was simple enough for a student and at the same time
meaningful. Some things just have to be bought on faith.

It's not hard.

All that's needed here is an example where there's a relationship
between the members. Stroustrup picked (in TC++PL) a Date class with
year, month and day-of-month. Then you eventually want to prevent
things like the 31th of February year 0, and there's suddenly a real
reason to have more than just a boring struct.

/Jorgen
 

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,734
Messages
2,569,441
Members
44,832
Latest member
GlennSmall

Latest Threads

Top