473,503 Members | 3,085 Online
Bytes | Software Development & Data Engineering Community
+ Post

Home Posts Topics Members FAQ

STL: copy vector of class ?

could someone please show/help me to copy all element from "class dog"
to "class new_dog" ?
Note: "class new_dog" has new element "age" which should have value
"my_age"
/////////////////////////////// source code
///////////////////////////////
#include<iostream>
#include <string>
#include<vector>
#include<sstream>
#include<fstream>
#include<numeric>
using namespace std;

class dog
{
public:
string name;
int id;
int YearBorn;
string type;
};

class new_dog
{
public:
string name;
int id;
string age;
string type;
};

#define goldenretriever 11
#define Lab 33
#define Boxer 44
#define Terrier 55
int const CurrentYear =2006;

int dog_name (const string& name,const string& type ,const int age);
int main()
{
vector<dog> v;
vector<new_dog> v2;

new_dog dog_type;
dog dog_class;

ifstream in ("test5e.txt");
string line;
while (!getline(in,line).eof()){
if (line.find("#")!=std::string::npos)continue;
istringstream is(line);
if(is>>dog_class.name>>dog_class.id>>dog_class.Yea rBorn>>dog_class.type)
{
v.push_back(dog_class);
}
}
vector<dog>::iterator search;
for (search=v.begin();search!=v.end();++search){
int my_age;
switch (search->id){
case goldenretriever:
my_age =dog_name(search->name,search->type,search->YearBorn);
//cout << "My dog is: "<<search->name<< " Age is :"<<
my_age<<endl;
break;
case Lab:
my_age=dog_name(search->name,search->type,search->YearBorn);
break;
case Boxer:
my_age=dog_name(search->name,search->type,search->YearBorn);
break;
case Terrier:
my_age=dog_name(search->name,search->type,search->YearBorn);
break;
default:
break;
} //switch

cout << "Dog name is: "<<search->name<< " ,Age is :"<<
my_age<<endl;
} // for loop

return 0;

}
int dog_name (const string& name,const string& type,int YearBorn){

return (CurrentYear-YearBorn);
}

/////////// input file "test5e.txt" //////////////////////////////

########################################
#Name ID YearBorn Type
########################################
Cricket 11 2000 GoldenRetriever
Nitro 11 1999 GoldenRetriever
Maxtor 33 2004 Lab
Arron 44 2001 Boxer
#Arron 44 2002 Boxer
Dora 55 2000 Terrier

Jan 24 '06 #1
18 2871
In article <11**********************@g43g2000cwa.googlegroups .com>,
"sd2004" <tv****@hotmail.com> wrote:
could someone please show/help me to copy all element from "class dog"
to "class new_dog" ?


The short answer is, don't do that. Make a member-function in the dog
class that accepts the current year as a parameter and returns the dog's
age.

I suspect this is a homework question so I won't give you the whole
answer, but I do want to help out.

int dog::age_at( int year ) { return year - year_born; }

--
Magic depends on tradition and belief. It does not welcome observation,
nor does it profit by experiment. On the other hand, science is based
on experience; it is open to correction by observation and experiment.
Jan 24 '06 #2

Daniel T. wrote:
In article <11**********************@g43g2000cwa.googlegroups .com>,
"sd2004" <tv****@hotmail.com> wrote:
could someone please show/help me to copy all element from "class dog"
to "class new_dog" ?


The short answer is, don't do that. Make a member-function in the dog
class that accepts the current year as a parameter and returns the dog's
age.

I suspect this is a homework question so I won't give you the whole
answer, but I do want to help out.

int dog::age_at( int year ) { return year - year_born; }


It makes absolutely no sense to have such a method in the interface of
'dog'. You need a method to return the 'yearOfBirth' of the dog (set at
construction), and then you can do whatever math you want with it.

Jan 24 '06 #3

"sd2004" <tv****@hotmail.com> wrote in message
news:11**********************@g43g2000cwa.googlegr oups.com...
| could someone please show/help me to copy all element from "class dog"
| to "class new_dog" ?
| Note: "class new_dog" has new element "age" which should have value
| "my_age"

Since you are taking an old class and adding features, why not inherit?
Isn't new_dog still a dog? (is_a relationship). In so far as age is
concerned, shouldn't that be a member function of the new_dog class
instead of a variable that needs to be modified on a specific birthday
for each instance? Isn't age() a new feature that should be deduced
dynamically based on a current date?

class Dog
{
const std::string name;
const int id;
const int YearBorn;
const std::string type;
public:
Dog(std::string s, int n, int y, std::string t); // hint: init list
virtual ~Dog();
/* member functions */
std::string getName() const;
int getID() const;
int getYearBorn() const;
std::string getType() const;
};

class NewDog : public Dog
{
public:
NewDog(std::string s, int n, int y, std::string t) : Dog(s, n, y, t)
{ }
~NewDog() { }
/* member functions */
int getAge(const int currentyear) const
{
return currentyear - getYearBorn();
}
};

|
| class new_dog
| {
| public:
| string name;
| int id;
| string age;
| string type;
| };
| /////////////////////////////// source code
| ///////////////////////////////
| #include<iostream>
| #include <string>
| #include<vector>
| #include<sstream>
| #include<fstream>
| #include<numeric>
| using namespace std;
|
| class dog
| {
| public:
| string name;
| int id;
| int YearBorn;
| string type;
| };
|
| class new_dog
| {
| public:
| string name;
| int id;
| string age;
| string type;
| };
|
| #define goldenretriever 11
| #define Lab 33
| #define Boxer 44
| #define Terrier 55
| int const CurrentYear =2006;
|
| int dog_name (const string& name,const string& type ,const int age);
| int main()
| {
| vector<dog> v;
| vector<new_dog> v2;
|
| new_dog dog_type;
| dog dog_class;
|
| ifstream in ("test5e.txt");
| string line;
| while (!getline(in,line).eof()){
| if (line.find("#")!=std::string::npos)continue;
| istringstream is(line);
|
if(is>>dog_class.name>>dog_class.id>>dog_class.Yea rBorn>>dog_class.type)
| {
| v.push_back(dog_class);
| }
| }
| vector<dog>::iterator search;
| for (search=v.begin();search!=v.end();++search){
| int my_age;
| switch (search->id){
| case goldenretriever:
| my_age =dog_name(search->name,search->type,search->YearBorn);
| //cout << "My dog is: "<<search->name<< " Age is :"<<
| my_age<<endl;
| break;
| case Lab:
| my_age=dog_name(search->name,search->type,search->YearBorn);
| break;
| case Boxer:
| my_age=dog_name(search->name,search->type,search->YearBorn);
| break;
| case Terrier:
| my_age=dog_name(search->name,search->type,search->YearBorn);
| break;
| default:
| break;
| } //switch
|
| cout << "Dog name is: "<<search->name<< " ,Age is :"<<
| my_age<<endl;
|
|
| } // for loop
|
| return 0;
|
| }
| int dog_name (const string& name,const string& type,int YearBorn){
|
| return (CurrentYear-YearBorn);
| }
|
| /////////// input file "test5e.txt" //////////////////////////////
|
| ########################################
| #Name ID YearBorn Type
| ########################################
| Cricket 11 2000 GoldenRetriever
| Nitro 11 1999 GoldenRetriever
| Maxtor 33 2004 Lab
| Arron 44 2001 Boxer
| #Arron 44 2002 Boxer
| Dora 55 2000 Terrier
|
Jan 24 '06 #4
I modified the source code as recommend by the expert as far as I
understood.
However , the compiler still give me error, could someone please help.
/////////////////// ERROR MESSAGE ////////////////////////////////

bash-2.05b$ g++ test5f.cpp
test5f.cpp: In function `int main()':
test5f.cpp:48: error: no matching function for call to
`std::vector<dog,
std::allocator<dog> >::push_back(int)'
/usr/include/c++/3.3.3/bits/stl_vector.h:596: error: candidates are:
void
std::vector<_Tp, _Alloc>::push_back(const _Tp&) [with _Tp = dog,
_Alloc =
std::allocator<dog>]
test5f.cpp:52: error: no matching function for call to
`std::vector<dog,
std::allocator<dog> >::push_back(int)'
/usr/include/c++/3.3.3/bits/stl_vector.h:596: error: candidates are:
void
std::vector<_Tp, _Alloc>::push_back(const _Tp&) [with _Tp = dog,
_Alloc =
std::allocator<dog>]
test5f.cpp:56: error: no matching function for call to
`std::vector<dog,
std::allocator<dog> >::push_back(int)'
/usr/include/c++/3.3.3/bits/stl_vector.h:596: error: candidates are:
void
std::vector<_Tp, _Alloc>::push_back(const _Tp&) [with _Tp = dog,
_Alloc =
std::allocator<dog>]
test5f.cpp:60: error: no matching function for call to
`std::vector<dog,
std::allocator<dog> >::push_back(int)'
/usr/include/c++/3.3.3/bits/stl_vector.h:596: error: candidates are:
void
std::vector<_Tp, _Alloc>::push_back(const _Tp&) [with _Tp = dog,
_Alloc =
std::allocator<dog>]
bash-2.05b$

/////////////////////////// source code //////////////////////////
#include<iostream>
#include <string>
#include<vector>
#include<sstream>
#include<fstream>
#include<numeric>
using namespace std;

class dog
{
public:
string name;
int id;
int YearBorn;
string type;
int age (const int year );
};
#define goldenretriever 11
#define Lab 33
#define Boxer 44
#define Terrier 55
int const CurrentYear =2006;

int dog_age (const string& name,const string& type ,const int age);
int main()
{
vector<dog> v;

dog dog_class;

ifstream in ("test5f.txt");
string line;
while (!getline(in,line).eof()){
if (line.find("#")!=std::string::npos)continue;
istringstream is(line);
if(is>>dog_class.name>>dog_class.id>>dog_class.Yea rBorn>>dog_class.type)
{
v.push_back(dog_class);
}
}
vector<dog>::iterator search;
for (search=v.begin();search!=v.end();++search){
int my_age;
switch (search->id){
case goldenretriever:
v.push_back(dog_class.age(search->YearBorn)); //line 48
//dog_class.age(search->YearBorn);
break;
case Lab:
v.push_back(dog_class.age(search->YearBorn)); //line 52
//dog_class.age(search->YearBorn);
break;
case Boxer:
v.push_back(dog_class.age(search->YearBorn)); // line 56
//dog_class.age(search->YearBorn);
break;
case Terrier:
v.push_back(dog_class.age(search->YearBorn)); // line 60
//dog_class.age(search->YearBorn);
break;
default:
break;
}

}

vector<dog>::iterator i;
for (i=v.begin();i!=v.end();++i){
//cout << "NEW Dog name: " <<i->e << " NEW Age: "<< i->age <<endl;
}
return 0;

}
int dog::age (const int year)
{
return (CurrentYear-YearBorn);
}

Jan 24 '06 #5

"sd2004" <tv****@hotmail.com> wrote in message
news:11**********************@o13g2000cwo.googlegr oups.com...
| I modified the source code as recommend by the expert as far as I
| understood.
| However , the compiler still give me error, could someone please help.
| /////////////////// ERROR MESSAGE ////////////////////////////////
|
| bash-2.05b$ g++ test5f.cpp
| test5f.cpp: In function `int main()':
| test5f.cpp:48: error: no matching function for call to
| `std::vector<dog,
| std::allocator<dog> >::push_back(int)'

I'm no expert but if you don't show minimum code, noone can help. You
should be pushing back the result of a NewDog ctor invocation into the
std::vector container, see main() below. ie:
dogs.push_back( NewDog("name", id, year, "type") );

I've left out the assignment operators for brevity and did not seperate
the headers and source for the same reason. Don't inject the code into
your project, learn the language instead (its worth it since very little
work is involved for considerable results). One doesn't construct a
moving car if he can't first construct one of its wheels. Run in debug
with breakpoints until you get it.

// Proj_Dog.cpp
#include <iostream>
#include <ostream>
#include <string>
#include <vector>

class Dog
{
std::string name;
int id;
int yearborn;
std::string type;
public:
/* ctor */
Dog(std::string s, int n, int y, std::string t)
: name(s), id(n), yearborn(y), type(t) { }
/* copy ctor */
Dog(const Dog& copy)
{
name = copy.name;
id = copy.id;
yearborn = copy.yearborn;
type = copy.type;
}
/* d~tor */
virtual ~Dog() { }
/* member functions */
std::string getName() const { return name; }
int getID() const { return id; }
int getYearBorn() const { return yearborn; }
std::string getType() const { return type; }
};

class NewDog : public Dog
{
public:
/* ctor */
NewDog(std::string s, int n, int y, std::string t) : Dog(s, n, y, t)
{ }
/* copy ctor */
NewDog(const NewDog& copy) : Dog(copy) { }
/* d~tor */
~NewDog() { }
/* member functions */
int getAge(const int currentyear) const
{
return currentyear - getYearBorn();
}
/* friend operators */
friend std::ostream& operator<<(std::ostream&, const NewDog&);
};

std::ostream& operator<<(std::ostream& os, const NewDog& nd)
{
os << "name:" << nd.getName();
os << " id:" << nd.getID();
os << " yearborn:" << nd.getYearBorn();
os << " type:" << nd.getType();
return os;
}

int main()
{
int id(0);
std::vector<NewDog> dogs; // our container
dogs.push_back( NewDog("dog_1", ++id, 2001, "type_1") );
dogs.push_back( NewDog("dog_2", ++id, 2002, "type_2") );
dogs.push_back( NewDog("dog_3", ++id, 2003, "type_3") );
dogs.push_back( NewDog("dog_4", ++id, 2004, "type_4") );

int year(2006); // the current year
typedef std::vector<NewDog>::iterator Iter;
Iter it = dogs.begin();
for (it; it != dogs.end(); ++it)
{
std::cout << *it;
std::cout << " age: " << (*it).getAge(year) << std::endl;
}
return 0;
}

/*
name:dog_1 id:1 yearborn:2001 type:type_1 age: 5
name:dog_2 id:2 yearborn:2002 type:type_2 age: 4
name:dog_3 id:3 yearborn:2003 type:type_3 age: 3
name:dog_4 id:4 yearborn:2004 type:type_4 age: 2
*/

obviously, the result of age is dependent on the value assigned to year.
Can you see how simple the exercise becomes once you friendify and
overload the global operator<< for a NewDog?

Now expand the NewDog class to serialize data to and from a file using
the same principle. Perhaps read(std::string& filename) and write(...)
might fit the bill.

Jan 25 '06 #6
In article <11*********************@o13g2000cwo.googlegroups. com>,
da********@warpmail.net wrote:
Daniel T. wrote:
In article <11**********************@g43g2000cwa.googlegroups .com>,
"sd2004" <tv****@hotmail.com> wrote:
could someone please show/help me to copy all element from "class dog"
to "class new_dog" ?


The short answer is, don't do that. Make a member-function in the dog
class that accepts the current year as a parameter and returns the dog's
age.

I suspect this is a homework question so I won't give you the whole
answer, but I do want to help out.

int dog::age_at( int year ) { return year - year_born; }


It makes absolutely no sense to have such a method in the interface of
'dog'. You need a method to return the 'yearOfBirth' of the dog (set at
construction), and then you can do whatever math you want with it.


Any algorithm that is used to determine the dog's age, should probably
also check for things like negative age, and probably also check to see
if the dog died before that year (and thus never reached that age.) In
other words, in a real program the algorithm would probably be much more
complicated that simply subtracting one number from another. Even if it
isn't, if the dog's age is needed in more than one place, "it makes
absolutely no sense" to duplicate the code required to determine the
dog's age. In that case the code should be placed in a function. Now,
where should that function be placed? The most logical place is in the
Dog class.

So yes, in any but the most simple programs, it does make sense to have
an age like function in the Dog class.
Jan 26 '06 #7

Daniel T. wrote:
In article <11*********************@o13g2000cwo.googlegroups. com>,
da********@warpmail.net wrote:
Daniel T. wrote:
In article <11**********************@g43g2000cwa.googlegroups .com>,
"sd2004" <tv****@hotmail.com> wrote:

> could someone please show/help me to copy all element from "class dog"
> to "class new_dog" ?

The short answer is, don't do that. Make a member-function in the dog
class that accepts the current year as a parameter and returns the dog's
age.

I suspect this is a homework question so I won't give you the whole
answer, but I do want to help out.

int dog::age_at( int year ) { return year - year_born; }


It makes absolutely no sense to have such a method in the interface of
'dog'. You need a method to return the 'yearOfBirth' of the dog (set at
construction), and then you can do whatever math you want with it.


Any algorithm that is used to determine the dog's age, should probably
also check for things like negative age, and probably also check to see
if the dog died before that year (and thus never reached that age.) In
other words, in a real program the algorithm would probably be much more
complicated that simply subtracting one number from another. Even if it
isn't, if the dog's age is needed in more than one place, "it makes
absolutely no sense" to duplicate the code required to determine the
dog's age. In that case the code should be placed in a function. Now,
where should that function be placed? The most logical place is in the
Dog class.


The proposed function is

int dog::age_at( int year ) { return year - year_born; }

This is a utility function, and belongs in something like DogUtil:

struct DogUtil {
//...

static int ageAt(const Dog& dog, int year);
// Return the non-negative age of the specified 'dog' in the
// specified 'year'. Return a negative value is 'year < 0', or
// 'year' is less than the year of birth of 'dog'.
};

A candidate member function might be

class Dog {
//...
public:
//...
int age() const;
// Return the current age of this dog.
};

Do you see the difference?

Jan 28 '06 #8
In article <11**********************@g49g2000cwa.googlegroups .com>,
da********@warpmail.net wrote:
The proposed function is

int dog::age_at( int year ) { return year - year_born; }

This is a utility function, and belongs in something like DogUtil:

struct DogUtil {
//...

static int ageAt(const Dog& dog, int year);
// Return the non-negative age of the specified 'dog' in the
// specified 'year'. Return a negative value is 'year < 0', or
// 'year' is less than the year of birth of 'dog'.
};
Will you agree with me that a dog's age is a piece of data that is
associated with the dog? If so, why is some other class providing that
data? And if not, why is it the *dog's* age?

What data is associated with DogUtil, or is it just a bag of functions?
A candidate member function might be

class Dog {
//...
public:
//...
int age() const;
// Return the current age of this dog.
};


The above would only work if the Dog class has a dependency on something
that can provide today's date. There's nothing wrong with that if there
are several Dog member-functions that also need to know today's date,
otherwise it is inappropriate. If this is the only member-function that
needs a date to produce the output, then it should accept the date as a
parameter.

My original proposed function has the added bonus of letting the client
determine the age of the dog at any particular year, whereas the
member-function you are proposing can only tell the "current age" of the
dog.
Jan 28 '06 #9
Daniel T. wrote:
Any algorithm that is used to determine the dog's age, should probably
also check for things like negative age, and probably also check to see
if the dog died before that year (and thus never reached that age.) In
other words, in a real program the algorithm would probably be much more
complicated that simply subtracting one number from another.
and:
da********@warpmail.net wrote:
The proposed function is

int dog::age_at( int 5year ) { return year - year_born; }

This is a utility function, and belongs in something like DogUtil:

struct DogUtil {
//...

static int ageAt(const Dog& dog, int year);
// Return the non-negative age of the specified 'dog' in the
// specified 'year'. Return a negative value is 'year < 0', or
// 'year' is less than the year of birth of 'dog'.
};


Will you agree with me that a dog's age is a piece of data that is
associated with the dog? If so, why is some other class providing that
data? And if not, why is it the *dog's* age?


Your proposal means to increase the number of members for the dog class
without sufficient cause. The proposed member yearOfBirth() provides all
necessary information and is a primitive, in terms of which other functions
can be defined. The proposed age() member lacks that property, in
particular if it would incorporate sanity checks like making sure the
result is non-negative.

Would you also opt for a member function

bool isOlderThan ( dog const & other );

or should that be a free standing function:

bool isOlder ( dog const & a, dog const & b ;

How would you implement it in terms of age() or in terms of yearOfBirth().
Note that there is a subtle difference between

bool isOlder( dog const & a, dog const & b ) {
return( a.yearOfBirth() < b.yearOfBirth() );
}

and

bool isOlderThan( dog const & a, dog const & b ) {
return( a.age( 0 ) > b.age( 0 ) );
}

namely that a.age(0) might throw since it is likely to yield a negative
result, at least for dogs born recently. Now, which year would you pick
instead of 0? If you have age also check whether the dog died already, you
are in even more trouble.

Of course, you could have both: a yearOfBirth() member and an age() member.
But where do you stop? Are you willing to add members to the dog class each
time some other piece of code would find those handy? Freestanding
functions can be added any time without the need to change the header
dog.h. That is, why I would opt for a primitive like yearOfBirth() instead
of an age() member function.
Best

Kai-Uwe Bux
Jan 28 '06 #10
In article <dr**********@murdoch.acc.Virginia.EDU>,
Kai-Uwe Bux <jk********@gmx.net> wrote:
Daniel T. wrote:
Any algorithm that is used to determine the dog's age, should probably
also check for things like negative age, and probably also check to see
if the dog died before that year (and thus never reached that age.) In
other words, in a real program the algorithm would probably be much more
complicated that simply subtracting one number from another.
and:
da********@warpmail.net wrote:
The proposed function is

int dog::age_at( int 5year ) { return year - year_born; }

This is a utility function, and belongs in something like DogUtil:

struct DogUtil {
//...

static int ageAt(const Dog& dog, int year);
// Return the non-negative age of the specified 'dog' in the
// specified 'year'. Return a negative value is 'year < 0', or
// 'year' is less than the year of birth of 'dog'.
};


Will you agree with me that a dog's age is a piece of data that is
associated with the dog? If so, why is some other class providing that
data? And if not, why is it the *dog's* age?


Your proposal means to increase the number of members for the dog class
without sufficient cause. The proposed member yearOfBirth() provides all
necessary information and is a primitive, in terms of which other functions
can be defined. The proposed age() member lacks that property, in
particular if it would incorporate sanity checks like making sure the
result is non-negative.

Would you also opt for a member function

bool isOlderThan ( dog const & other );

or should that be a free standing function:

bool isOlder ( dog const & a, dog const & b ;


In this case, 'isOlder' should be a free standing function, because it
is not a property of any particular dog, but rather a comparison of two
different dogs.

Again, are you saying that a dog's age is not a property of the dog?
Of course, you could have both: a yearOfBirth() member and an age() member.
But where do you stop? Are you willing to add members to the dog class each
time some other piece of code would find those handy?


I add the member-function when there is some duplication (which tells us
that a function is a good idea) and the code is logically a property of
the class.
Jan 28 '06 #11
Daniel T. wrote:
In article <dr**********@murdoch.acc.Virginia.EDU>,
Kai-Uwe Bux <jk********@gmx.net> wrote:
Daniel T. wrote:
> Any algorithm that is used to determine the dog's age, should probably
> also check for things like negative age, and probably also check to see
> if the dog died before that year (and thus never reached that age.) In
> other words, in a real program the algorithm would probably be much
> more complicated that simply subtracting one number from another.


and:
> da********@warpmail.net wrote:
>
>> The proposed function is
>>
>> int dog::age_at( int 5year ) { return year - year_born; }
>>
>> This is a utility function, and belongs in something like DogUtil:
>>
>> struct DogUtil {
>> //...
>>
>> static int ageAt(const Dog& dog, int year);
>> // Return the non-negative age of the specified 'dog' in the
>> // specified 'year'. Return a negative value is 'year < 0',
>> or // 'year' is less than the year of birth of 'dog'.
>> };
>
> Will you agree with me that a dog's age is a piece of data that is
> associated with the dog? If so, why is some other class providing that
> data? And if not, why is it the *dog's* age?


Your proposal means to increase the number of members for the dog class
without sufficient cause. The proposed member yearOfBirth() provides all
necessary information and is a primitive, in terms of which other
functions can be defined. The proposed age() member lacks that property,
in particular if it would incorporate sanity checks like making sure the
result is non-negative.

Would you also opt for a member function

bool isOlderThan ( dog const & other );

or should that be a free standing function:

bool isOlder ( dog const & a, dog const & b ;


In this case, 'isOlder' should be a free standing function, because it
is not a property of any particular dog, but rather a comparison of two
different dogs.

Again, are you saying that a dog's age is not a property of the dog?


Well, I fail to see how you maintain that age is a property whereas isOlder
is a relation:

* isOlder is a relation between two dogs, i.e., a function that
maps ordered pairs of dogs to truth-values. A signature
representing that would read:

bool isOlder ( Dog const &, Dog const & );

* age() is a function that maps an ordered pair of a dog and a year
to a number. Here the corresponding signature reads:

int age_in_year ( Dog const &, int );

From this signature it is also clear that, if you consider age as a property
of the dog, you should also (by symmetry) consider it a property of the
year. Now, if you had a Year class, would you propose a member function:

class Year {
...

int age ( Dog const & );

};

BTW: since there is no year 0 in our calendar, a Year class is less silly
than one might think.

There really is no difference: being older than my puppy is of course a
property of dogs in the same way that being 8 years old in the year 2008 is
a property of dogs. And of course, being a year in which my puppy is 12, is
a property of years.

I cannot bring myself to take "is a property of" as a valid guideline for
class design.

Of course, you could have both: a yearOfBirth() member and an age()
member. But where do you stop? Are you willing to add members to the dog
class each time some other piece of code would find those handy?


I add the member-function when there is some duplication (which tells us
that a function is a good idea) and the code is logically a property of
the class.


Based on the demonstrated parallelism between isOlder() and age(), I would
maintain that being "logically property of the class" is not a good
guideline. Instead, I would try to go with free-standing functions as much
as possible. Within the class, I would put the bare minimum of primitives
needed to implement the free-standing functions as non-friends.

Of course, ultimately, I probably do not follow rules but gutt feelings
about what is most appropriate in a particular case. And, I guess, it is
those gutt feelings that tell me in this case, that age() should be
free-standing and the class should have a dateOfBirth() member instead.
Best

Kai-Uwe Bux
Jan 28 '06 #12

Kai-Uwe Bux wrote:
Daniel T. wrote:
Any algorithm that is used to determine the dog's age, should probably
also check for things like negative age, and probably also check to see
if the dog died before that year (and thus never reached that age.) In
other words, in a real program the algorithm would probably be much more
complicated that simply subtracting one number from another.


and:
da********@warpmail.net wrote:
The proposed function is

int dog::age_at( int 5year ) { return year - year_born; }

This is a utility function, and belongs in something like DogUtil:

struct DogUtil {
//...

static int ageAt(const Dog& dog, int year);
// Return the non-negative age of the specified 'dog' in the
// specified 'year'. Return a negative value is 'year < 0', or
// 'year' is less than the year of birth of 'dog'.
};


Will you agree with me that a dog's age is a piece of data that is
associated with the dog? If so, why is some other class providing that
data? And if not, why is it the *dog's* age?


Your proposal means to increase the number of members for the dog class
without sufficient cause. The proposed member yearOfBirth() provides all
necessary information and is a primitive, in terms of which other functions
can be defined. The proposed age() member lacks that property, in
particular if it would incorporate sanity checks like making sure the
result is non-negative.

Would you also opt for a member function

bool isOlderThan ( dog const & other );

or should that be a free standing function:

bool isOlder ( dog const & a, dog const & b ;

How would you implement it in terms of age() or in terms of yearOfBirth().
Note that there is a subtle difference between

bool isOlder( dog const & a, dog const & b ) {
return( a.yearOfBirth() < b.yearOfBirth() );
}

and

bool isOlderThan( dog const & a, dog const & b ) {
return( a.age( 0 ) > b.age( 0 ) );
}

namely that a.age(0) might throw since it is likely to yield a negative
result, at least for dogs born recently. Now, which year would you pick
instead of 0? If you have age also check whether the dog died already, you
are in even more trouble.

Of course, you could have both: a yearOfBirth() member and an age() member.
But where do you stop? Are you willing to add members to the dog class each
time some other piece of code would find those handy? Freestanding
functions can be added any time without the need to change the header
dog.h. That is, why I would opt for a primitive like yearOfBirth() instead
of an age() member function.


Just to clarify, Kai-Uwe is talking about 'int age_at(int year)', not
'const int age() const'. The names keep changing :-)

If you look at the two original class definitions, one has a 'YearBorn'
member, and the other has an 'age' member (although the type is
'string'). When your class represents a value, such as the dog classes
in this thread, good practice dictates that you have accessors an
manipulators (where appropriate) corresponding to the data members of
the class, and utilities that operate on class instances. You do not
typically add methods to the class to perform some random function,
like subtract the 'YearBorn' member from a random integer.

Jan 28 '06 #13
In article <11**********************@o13g2000cwo.googlegroups .com>,
da********@warpmail.net wrote:
Just to clarify, Kai-Uwe is talking about 'int age_at(int year)', not
'const int age() const'. The names keep changing :-)
Not just the names, but the dependencies as well. 'age' has an implicit
dependency on whatever produces the current date, 'age_at' doesn't.
If you look at the two original class definitions, one has a 'YearBorn'
member, and the other has an 'age' member (although the type is
'string').
I have nothing against a 'yearBorn' member-function, by all means put it
in as well.
When your class represents a value, such as the dog classes
in this thread, good practice dictates that you have accessors an
manipulators (where appropriate) corresponding to the data members of
the class, and utilities that operate on class instances.
Where in the world did you get that from? The Dog class is a primary
abstraction of the problem space. I have no problem with the accessors
and manipulators, until you tell me they have to be removed/changed if
the member-variable is removed/changed. That breaks encapsulation in a
big way.
You do not
typically add methods to the class to perform some random function,
like subtract the 'YearBorn' member from a random integer.


The age of the dog is certainly not a "random function", it is important
to the problem space.

--
Magic depends on tradition and belief. It does not welcome observation,
nor does it profit by experiment. On the other hand, science is based
on experience; it is open to correction by observation and experiment.
Jan 28 '06 #14
In article <dr*********@murdoch.acc.Virginia.EDU>,
Kai-Uwe Bux <jk********@gmx.net> wrote:
Again, are you saying that a dog's age is not a property of the dog?


Well, I fail to see how you maintain that age is a property whereas isOlder
is a relation:

* isOlder is a relation between two dogs, i.e., a function that
maps ordered pairs of dogs to truth-values. A signature
representing that would read:

bool isOlder ( Dog const &, Dog const & );

* age() is a function that maps an ordered pair of a dog and a year
to a number. Here the corresponding signature reads:

int age_in_year ( Dog const &, int );

From this signature it is also clear that, if you consider age as a property
of the dog, you should also (by symmetry) consider it a property of the
year. Now, if you had a Year class, would you propose a member function:

class Year {
...

int age ( Dog const & );

};


Do you really think that a dog's age is the property of the current
year? Does that make *any* sense? How often have you asked someone
which year his dog's age belongs to?
Jan 28 '06 #15
Daniel T. wrote:
In article <dr*********@murdoch.acc.Virginia.EDU>,
Kai-Uwe Bux <jk********@gmx.net> wrote:
> Again, are you saying that a dog's age is not a property of the dog?


Well, I fail to see how you maintain that age is a property whereas
isOlder is a relation:

* isOlder is a relation between two dogs, i.e., a function that
maps ordered pairs of dogs to truth-values. A signature
representing that would read:

bool isOlder ( Dog const &, Dog const & );

* age() is a function that maps an ordered pair of a dog and a year
to a number. Here the corresponding signature reads:

int age_in_year ( Dog const &, int );

From this signature it is also clear that, if you consider age as a
property of the dog, you should also (by symmetry) consider it a property
of the year. Now, if you had a Year class, would you propose a member
function:

class Year {
...

int age ( Dog const & );

};


Do you really think that a dog's age is the property of the current
year? Does that make *any* sense? [snip]


Well, a widely used calendar is apparently based on the assumption that the
age of Jesus Christ is a somehow significant property of a given year :-)
So, what about:

class Year {

int age_of ( Entity const & default = Static_Humans::Jesus_Christ );

}
Best

Kai-Uwe Bux
Jan 28 '06 #16

Daniel T. wrote:
In article <11**********************@o13g2000cwo.googlegroups .com>,
da********@warpmail.net wrote:
Just to clarify, Kai-Uwe is talking about 'int age_at(int year)', not
'const int age() const'. The names keep changing :-)
Not just the names, but the dependencies as well. 'age' has an implicit
dependency on whatever produces the current date, 'age_at' doesn't.


'age' depends on standard library functions (e.g. 'std::time', etc).
This is a perfectly reasonable dependency. However, I am not
recommending that 'age' be in the interface of 'Dog', except that if
you wanted to return the dog's age in addition to the year of birth,
returning the current age is a much more reasonable method than one
which returns the age based on a random input: current age is a
"derived" property of 'YearBorn', and requires none of the range
checking 'age_at' does.
If you look at the two original class definitions, one has a 'YearBorn'
member, and the other has an 'age' member (although the type is
'string').


I have nothing against a 'yearBorn' member-function, by all means put it
in as well.
When your class represents a value, such as the dog classes
in this thread, good practice dictates that you have accessors an
manipulators (where appropriate) corresponding to the data members of
the class, and utilities that operate on class instances.


Where in the world did you get that from?


Lakos '96.
The Dog class is a primary
abstraction of the problem space. I have no problem with the accessors
and manipulators, until you tell me they have to be removed/changed if
the member-variable is removed/changed. That breaks encapsulation in a
big way.
You do not
typically add methods to the class to perform some random function,
like subtract the 'YearBorn' member from a random integer.


The age of the dog is certainly not a "random function", it is important
to the problem space.


There is a difference between 'age' taking no arguments, and 'age_at',
which takes a year as input. "Current age" is a property of Dog. "Age
at year X" is not; it is a function of Dog and year.

Jan 29 '06 #17
In article <dr**********@murdoch.acc.Virginia.EDU>,
Kai-Uwe Bux <jk********@gmx.net> wrote:
Daniel T. wrote:
In article <dr*********@murdoch.acc.Virginia.EDU>,
Kai-Uwe Bux <jk********@gmx.net> wrote:
> Again, are you saying that a dog's age is not a property of the dog?

Well, I fail to see how you maintain that age is a property whereas
isOlder is a relation:

* isOlder is a relation between two dogs, i.e., a function that
maps ordered pairs of dogs to truth-values. A signature
representing that would read:

bool isOlder ( Dog const &, Dog const & );

* age() is a function that maps an ordered pair of a dog and a year
to a number. Here the corresponding signature reads:

int age_in_year ( Dog const &, int );

From this signature it is also clear that, if you consider age as a
property of the dog, you should also (by symmetry) consider it a property
of the year. Now, if you had a Year class, would you propose a member
function:

class Year {
...

int age ( Dog const & );

};


Do you really think that a dog's age is the property of the current
year? Does that make *any* sense? [snip]


Well, a widely used calendar is apparently based on the assumption that the
age of Jesus Christ is a somehow significant property of a given year :-)
So, what about:

class Year {

int age_of ( Entity const & default = Static_Humans::Jesus_Christ );

}


We are talking about a program where 'dog' is a primary abstraction,
perhaps a vet's patient database, do *you* think that
"year::age_of_Jesus_Christ" is an appropriate function of such a program?
Jan 29 '06 #18
Daniel T. wrote:
In article <dr**********@murdoch.acc.Virginia.EDU>,
Kai-Uwe Bux <jk********@gmx.net> wrote:
Daniel T. wrote:
> In article <dr*********@murdoch.acc.Virginia.EDU>,
> Kai-Uwe Bux <jk********@gmx.net> wrote:
>
>> > Again, are you saying that a dog's age is not a property of the dog?
>>
>> Well, I fail to see how you maintain that age is a property whereas
>> isOlder is a relation:
>>
>> * isOlder is a relation between two dogs, i.e., a function that
>> maps ordered pairs of dogs to truth-values. A signature
>> representing that would read:
>>
>> bool isOlder ( Dog const &, Dog const & );
>>
>> * age() is a function that maps an ordered pair of a dog and a year
>> to a number. Here the corresponding signature reads:
>>
>> int age_in_year ( Dog const &, int );
>>
>> From this signature it is also clear that, if you consider age as a
>> property of the dog, you should also (by symmetry) consider it a
>> property of the year. Now, if you had a Year class, would you propose
>> a member function:
>>
>> class Year {
>> ...
>>
>> int age ( Dog const & );
>>
>> };
>
> Do you really think that a dog's age is the property of the current
> year? Does that make *any* sense? [snip]


Well, a widely used calendar is apparently based on the assumption that
the age of Jesus Christ is a somehow significant property of a given year
:-) So, what about:

class Year {

int age_of ( Entity const & default = Static_Humans::Jesus_Christ );

}


We are talking about a program where 'dog' is a primary abstraction,
perhaps a vet's patient database, do *you* think that
"year::age_of_Jesus_Christ" is an appropriate function of such a program?


a) Please, lighten up. Did you, by any chance, miss the "this is a joke
flag"?

b) I just gave reasons why I would prefer a free standing function

int age_of_in_year ( Dog const & dog, int year );

to a member function

class Dog {

int age_in_year ( int year );

}

In that part of the argument where I tried to refute your reasoning, I
applied your criterion (namely the phrase "is a property of") in ways that
you did not forsee just to demonstrate why I would not consider it a good
guideline for class design. That's all.

DISCLAIMER: That counter-argument, of course, does not apply to any other
reasons that you may or may not have to prefer a member function to a free
standing function in this particular case.

However, the way you iterate the question

"Again, are you saying that a dog's age is not a property of the dog?"

indicates that this seems to be a very important point to you. In direct
response: I agree that age is a property of the dog; but that is completely
inconsequential for whether it should be a member function or a free
standing function.
Best

Kai-Uwe
Jan 29 '06 #19

This thread has been closed and replies have been disabled. Please start a new discussion.

Similar topics

2
3731
by: forums_mp | last post by:
I've got an STL class (see below) with two functions to store and retrieve data - msg structs. The "Store" function when called will copy the received message (depending on which message) into...
8
2187
by: Generic Usenet Account | last post by:
To settle the dispute regarding what happens when an "erase" method is invoked on an STL container (i.e. whether the element is merely removed from the container or whether it also gets deleted in...
25
2237
by: rokia | last post by:
in a project, I use many,many stl such as stack,list,vctor etc. somewhere the vector's size is more than 2K. is this a efficient way?
9
1866
by: Aguilar, James | last post by:
Hey guys. A new question: I want to use an STL libarary to hold a bunch of objects I create. Actually, it will hold references to the objects, but that's beside the point, for the most part. ...
11
2882
by: Richard Thompson | last post by:
I've got a memory overwrite problem, and it looks as if a vector has been moved, even though I haven't inserted or deleted any elements in it. Is this possible? In other words, are there any...
35
2592
by: Jon Slaughter | last post by:
I'm having a problem allocating some elements of a vector then deleting them. Basicaly I have something like this: class base { private: std::vector<object> V;
11
4726
by: ma740988 | last post by:
I'm perusing a slide with roughly 12 bullets spread across 3 pages. Each bullet reflects 'advice'. I'm ok with all but 1 bullet, more specifically the bullet that states: " Avoid the STL unless...
4
1750
by: Generic Usenet Account | last post by:
I am seeing some unexpected behavior while using the STL "includes" algorithm. I am not sure if this is a bug with the template header files in our STL distribution, or if this is how it should...
1
3057
by: krunalbauskar | last post by:
Hi, Explicit instantiation of STL vector demands explicit instantiation of all the templates it using internally. For example - <snippet> #include <iostream> #include <vector>
6
3916
by: Peng Yu | last post by:
Hi, I'm wondering if the following assignment is lazy copy or not? Thanks, Peng std::vector<intv. v.push_back(1); v.push_back(2);
0
7207
marktang
by: marktang | last post by:
ONU (Optical Network Unit) is one of the key components for providing high-speed Internet services. Its primary function is to act as an endpoint device located at the user's premises. However,...
0
7291
Oralloy
by: Oralloy | last post by:
Hello folks, I am unable to find appropriate documentation on the type promotion of bit-fields when using the generalised comparison operator "<=>". The problem is that using the GNU compilers,...
0
7357
jinu1996
by: jinu1996 | last post by:
In today's digital age, having a compelling online presence is paramount for businesses aiming to thrive in a competitive landscape. At the heart of this digital strategy lies an intricately woven...
0
7468
tracyyun
by: tracyyun | last post by:
Dear forum friends, With the development of smart home technology, a variety of wireless communication protocols have appeared on the market, such as Zigbee, Z-Wave, Wi-Fi, Bluetooth, etc. Each...
0
5598
agi2029
by: agi2029 | last post by:
Let's talk about the concept of autonomous AI software engineers and no-code agents. These AIs are designed to manage the entire lifecycle of a software development project—planning, coding, testing,...
0
3180
by: TSSRALBI | last post by:
Hello I'm a network technician in training and I need your help. I am currently learning how to create and manage the different types of VPNs and I have a question about LAN-to-LAN VPNs. The...
0
3171
by: adsilva | last post by:
A Windows Forms form does not have the event Unload, like VB6. What one acts like?
1
748
muto222
by: muto222 | last post by:
How can i add a mobile payment intergratation into php mysql website.
0
402
bsmnconsultancy
by: bsmnconsultancy | last post by:
In today's digital era, a well-designed website is crucial for businesses looking to succeed. Whether you're a small business owner or a large corporation in Toronto, having a strong online presence...

By using Bytes.com and it's services, you agree to our Privacy Policy and Terms of Use.

To disable or enable advertisements and analytics tracking please visit the manage ads & tracking page.