Solved

C++ Interleaved classes Question

Posted on 2003-11-16
11
298 Views
Last Modified: 2010-04-01
Hello all,

I am doing this assignment and I encounter an error.  Below is my code:

#include <string>
#include <iostream>
#include <vector>
#include <list>

using namespace std;

class Toast;
class SmartTurkey;
class Turkey;
class Person;

// To init.
class Date {
    int month;
    int day;
    int year;

public:
    //Date(): month(0), day(0), year(0) {};
    Date();
    Date( int m, int d, int y );

    friend ostream& operator<<( ostream& os, const Date* d );
}; // class Date {}


class DinnerParty {
    static const float ApplePi = 3.14;
    Date partyDate;
    Toast* beverage;
    SmartTurkey *courses;
    vector<Person*> gobblers;
    int storage;

public:
    DinnerParty();
    DinnerParty( Date p, Toast* b, SmartTurkey* c, int temp, vector<Person*> g );
   
    DinnerParty( const DinnerParty& other);
    DinnerParty& operator=( const DinnerParty& other);
    friend ostream& operator<<( ostream& os, const DinnerParty& dp );
    ~DinnerParty();
}; // class DinnerParty {}


class Person {
    string name;
    vector<Person*> friends;
    Toast* favoriteDrink;

public:
    Person();
    Person( string n, vector<Person*> f, Toast* fd );
    Person( string n, Toast* fd);
    Person( string n);
   
    Person& operator=( const Person& other);
    Person( const Person& other);
    friend ostream& operator<<( ostream& os, const Person& p );
    ~Person();
}; // class Person {}


class SmartTurkey {
    string stuffing;
    Turkey* roasted;

public:
      
    SmartTurkey();
    SmartTurkey(string makeTemp, Turkey* makeTemp1);
   
    SmartTurkey& operator=(const SmartTurkey& other);
    SmartTurkey(const SmartTurkey& other);
   
    friend ostream& operator<<( ostream& os, const SmartTurkey& p );
    ~SmartTurkey();
}; // class SmartTurkey {}


class Toast {
    string beverageName;
    int year;
      Person proposer;

public:
    Toast();
    Toast( string bn, int y, Person p );
   
    friend ostream& operator<<( ostream& os, const Toast& t );
}; // class Toast {}


class Turkey {
    string name;
    int age;
    Person owner;

public:
    Turkey();
    Turkey( string n, int a, Person o );
   
    friend ostream& operator<<( ostream& os, const Turkey& t );
}; // class Turkey {}

/* Date */

Date::Date() :
month(0), day(0), year(0) {}

Date::Date( int m, int d, int y ): month(m), day(d), year(y) {}

/* Dinner Party */
DinnerParty::DinnerParty() :
partyDate(Date(0,0,0)),beverage(0), courses(0), storage(0) {}

DinnerParty::DinnerParty( Date p, Toast* b, SmartTurkey *c, int temp, vector<Person*> g):

partyDate(p), storage(temp),gobblers(g)
{

if (b == 0){
  beverage = 0;
}
else{
  beverage = new Toast(*b);
}

if (temp != 0)
{
  courses = new SmartTurkey[temp];
  for (int i = 0; i < temp; i++)
    courses[i] = c[i];
}
else
  courses = 0;
}

// copy constructor:
DinnerParty::DinnerParty( const DinnerParty& other) :
  partyDate(other.partyDate), beverage(other.beverage), storage(other.storage), gobblers(other.gobblers)
{
  if (other.storage != 0)
  {
    courses = new SmartTurkey[storage];
    for (int i = 0; i<storage; i++)
      courses[i] = other.courses[i];
  }
  else
    courses = 0;
}

//Copy assignment operator:
DinnerParty& DinnerParty::operator=(const DinnerParty& other)
{
  if (this == &other) return *this;
 
  partyDate = other.partyDate;
  beverage = other.beverage;
  storage = other.storage;
  gobblers = other.gobblers;

  if (this->courses != 0)
    delete[] courses;
   
  if (other.courses != 0)
    for (int i = 0; i<storage; i++)
      this->courses[i] = other.courses[i];
  else
    courses = 0;
   
  return *this;
 
}
// Destructor:
DinnerParty::~DinnerParty()
{
  if (beverage != 0)
    delete beverage;
}

/* Person */
Person::Person()
{
favoriteDrink = 0;
}

Person::Person( string n, vector<Person*> f, Toast* fd ) :
  name(n),  
  friends(f)
{
  if ( fd == 0) favoriteDrink = 0;
    else favoriteDrink = new Toast(*fd);
}

Person::Person( string n, Toast* fd):
  name(n)
{
  if (fd == 0)
    favoriteDrink = 0;
  else
    favoriteDrink = new Toast(*fd);
}

Person::Person( string n) :
  name(n)
  {
    favoriteDrink = 0;
  }


// Copy constructor:
Person::Person( const Person& other) :  
  name(other.name),friends(other.friends)
{
  if (other.favoriteDrink != 0)
    favoriteDrink = new Toast(*(other.favoriteDrink));
  else
    favoriteDrink = 0;

}
 
// Copy assignment:
Person& Person::operator=( const Person& other)
{
  if (this == &other) return *this;
 
  name = other.name;
  friends = other.friends;
 
  if (this->favoriteDrink != 0)
    delete favoriteDrink;
   
  if (other.favoriteDrink != 0)
    favoriteDrink = new Toast(*other.favoriteDrink);
  else
    favoriteDrink = 0;
   
  return *this;
}

//  Destructor
Person::~Person()
{
  if (favoriteDrink != 0)
    delete favoriteDrink;  
}

// Constructor
SmartTurkey::SmartTurkey() :
  roasted(0) {}
 
  SmartTurkey::SmartTurkey(string makeTemp, Turkey* makeTemp1) :
    stuffing(makeTemp)
  {
    if (makeTemp1 == 0)
      roasted = 0;
    else
      roasted = new Turkey(*makeTemp1);
  }

// Copy constructor  
SmartTurkey::SmartTurkey(const SmartTurkey& other) :
  stuffing(other.stuffing)
{
  if (other.roasted != 0)
    roasted = new Turkey(*other.roasted);
  else
    roasted = 0;

 }
 
// Copy Assignment
SmartTurkey& SmartTurkey::operator=( const SmartTurkey& other)
{  
  if (this == &other) return *this;
 
  stuffing = other.stuffing;
 
  if (this->roasted != 0)
    delete roasted;
   
  if (other.roasted != 0)
    roasted = new Turkey(*other.roasted);
  else
    roasted = 0;
   
  return *this;
}

// Destructor
SmartTurkey::~SmartTurkey()
{
  if (roasted != 0)
    delete roasted;  
}

Toast::Toast():
  year(0), proposer(Person()){}
 
Toast::Toast( string bn, int y, Person p) :
  beverageName(bn),
  year(y),
  proposer(p){}
 
Turkey::Turkey():
  age(0){}
   
Turkey::Turkey( string n, int a, Person o) :
  name(n.c_str()),
  age(a)
  {
    owner = o;
  }
 
/*-------------------------------------------------------------------*/  

// Ostream for Date()  
ostream& operator<<( ostream& os, const Date* d)
{
  os << "Date: ";
  os << d->month << "/";
  os << d->day << "/";
  os << d->year << endl;
  return os;
}

// Ostream for DinnerParty
ostream& operator<<( ostream& os, const DinnerParty& dp)
{
  os << "Date of Party :" << &dp.partyDate;
  os << *dp.beverage;
 
  if (dp.storage != 0)
  {
    for (int i = 0; i < dp.storage; i++)
      os << (dp.courses[i]);
  }
 
  if (dp.gobblers.begin() != dp.gobblers.end())
  {
    vector<Person*>::const_iterator q = dp.gobblers.begin();
    while (q != dp.gobblers.end())
    {
      os << "Other people is/are :" << **q++;
    }
  }
  return os;
}

// Ostream for Person
ostream& operator<<( ostream& os, const Person& p)
{
  os << "Name Info: " << p.name << endl;
  if (p.favoriteDrink != 0)
    os << "Toast " << *(p.favoriteDrink) << endl;
 
  if (p.friends.begin() != p.friends.end())
  {
    vector<Person*>::const_iterator q = p.friends.begin();
    while (q != p.friends.end())
      cout << "Friends" << **q++;
      os << endl;
  }  
  return os;
}

// Ostream for SmartTurkey
ostream& operator<<( ostream& os, const SmartTurkey& p)
{
  os << "Stuffing : " << p.stuffing << endl;
  os << "Brand: " << *(p.roasted);
  return os;
}

// Ostream for Toast
ostream& operator<<( ostream& os, const Toast& t)
{
  os << "Type of Drink : " << t.beverageName << endl;
  os << "How Old: " << t.year << endl;
  os << "Toaster " << t.proposer;
  return os;
}


// OStream for Turkey
ostream& operator<<( ostream& os, const Turkey& t)
{
 os << "Name: " << t.name << endl;
 os << "Age:  " << t.age << endl;
 os << "Turkey Owner's " << t.owner;
 return os;
}

int main() {
  //OUTPUT6
  cout << "\n\nOUTPUT 6: " << endl;
  DinnerParty ALL(v, &bday, NumArray,temp, st);
  cout << ALL;  
} // main()

The output is :

OUTPUT 6:
Date of Party :Date: 11/14/2003
Type of Drink : Starbucks Coffee
How Old: 56
Toaster Name Info: Mike
FriendsName Info: Eric
FriendsName Info: David

My question is
1)why it's not showing the date after "Date of Party?"  
2)Why can't I write everything insdie of first class definition..instead, i have to write
class Toast;
class SmartTurkey;
class Turkey;
class Person;

at the beginning of the code and the rest of definition (like..copy contructors..etc..after the first class definition).  This works because I followed my textbook.

Sorry about this long code..i am just really curious abouto this problem...Thanks  Any hint will be appreicated..

Thanks
0
Comment
Question by:daskino12
  • 6
  • 4
11 Comments
 
LVL 4

Expert Comment

by:n_fortynine
ID: 9760028
1) What do you mean? Didn't the output show:
>>Date of Party :Date: 11/14/2003
2) Because one class is using another and itself in turn is being used by the "other" (for example: Toast uses Person and Person uses Toast.) Technically you don't have to declare Turkey at all just need to make sure Turkey is defined above DinnerParty. If you have class A using class B, the compiler will look for any reference to class B PRIOR to that position of code (or in any included files), and it must known what B is or at least B is declared.
0
 

Author Comment

by:daskino12
ID: 9760228
Hello,

I am sorry about the first question. I got it...i got somethign wrong...anyway, thanks..i undersatnd the second questions now.

I was just wondering, is it possible for me to put  Ostream part inside of my first class definition?  I have tried it yet it gave me errors..

Thanks
0
 

Author Comment

by:daskino12
ID: 9760237
Hello,

I am sorry but from my textbook, it didn't declare all the class at the beginning of the program.  Do you know why?  I thought you have to do that (according to  n_fortynine's comments).  Or, it is not necessary...

THanks
0
 
LVL 4

Expert Comment

by:n_fortynine
ID: 9760246
>>I was just wondering, is it possible for me to put  Ostream part inside of my first class definition?  I have tried it yet it
>>gave me errors..
Could you please be more specific, say, which class is it? normally you have to make it a friend.
friend ostream& operator << ( ... )
0
 
LVL 11

Expert Comment

by:bcladd
ID: 9760274
Usually  the function

ostream& operator<<

is used between an ostream and an object of a user defined class to "print out" the object (or rather to insert the object into the stream). When you put binary operators into a class, the left hand side of the operator MUST be an object of the defining class. So, you could define an operator<< inside of Toast (for example), but it could only work if the left hand side of << (when used) is of type Toast. Since you want to insert a Toast into an output stream you must either:
(1) Modify the definition of the class ostream
(2) Write a global operator that specifies both the left hand and right hand sides of the operator.

(1) Is infeasible. (2) works an usually you make the operator a friend so that it is part of the class interface and can access private data members of the class.

Hope this helps,
-bcl
0
Why You Should Analyze Threat Actor TTPs

After years of analyzing threat actor behavior, it’s become clear that at any given time there are specific tactics, techniques, and procedures (TTPs) that are particularly prevalent. By analyzing and understanding these TTPs, you can dramatically enhance your security program.

 

Author Comment

by:daskino12
ID: 9760294
Hello,

So, for example, i can do theh following:

using namespace std;

class Toast;
class SmartTurkey;
class Turkey;
class Person;

// To init.
class Date {
    int month;
    int day;
    int year;

public:
    //Date(): month(0), day(0), year(0) {};
    Date();
    Date( int m, int d, int y );

    friend ostream& operator<<( ostream& os, const Date* d );
}; // class Date {}

..

..

/* Date */

Date::Date() :
month(0), day(0), year(0) {}
Date::Date( int m, int d, int y ): month(m), day(d), year(y) {}
ostream& operator<<( ostream& os, const Date* d)
{
  os << "Date: ";
  os << d->month << "/";
  os << d->day << "/";
  os << d->year << endl;
  return os;
}

all in one block, right?

THanks
0
 

Author Comment

by:daskino12
ID: 9760309
Hello,

Ok.  Now, one of my unclear question above is, can I write everything at the first part of class

Like

class Date {
    int month;
    int day;
    int year;

public:
    //Date(): month(0), day(0), year(0) {};
    Date();
    Date( int m, int d, int y );

    friend ostream& operator<<( ostream& os, const Date* d );
}; // class Date {}

without declearing the following then?

class Toast;
class SmartTurkey;
class Turkey;
class Person;

Um..it seems it doesn't work because as  n_fortynine said, for eample, Toast used Person..Person uses Toast..but is there a way to do it differetly?  The reason i am asking this is because i think i have leart a way but i just forgot how to do it...not too sure..anyway...thanks:)

0
 
LVL 4

Expert Comment

by:n_fortynine
ID: 9760344
daskino12:

If a class, say Date does not use any other classes then it can be defined BEFORE any other classes THAT USES IT without having to forward declare it. Otherwise, C++ does not allow a way around it.

For example:

class ClassThatDateUseIfAny {
  //...
};

class ClassThatDoesNotUseDate {
  //...
};

class Date {
  //...
};

class ClassThatUsesDate {
  //...
};

0
 

Author Comment

by:daskino12
ID: 9761275
Hello,

I am sorry..can u like.plez .explain a bit more? I am so sorry.i. am a beginner...

Thnaks
0
 
LVL 4

Accepted Solution

by:
n_fortynine earned 500 total points
ID: 9761776
Well, in short here's how it goes. You CANNOT use a class without the compiler knowing what it is.

class A {
   B instance_of_B; //compiler does not know what B is consist of to handle this.
};

so you'll have to do AT LEAST the following, which is called forward declaration:

class B; //notice that you don't have to give the detailed description of class B at this moment.

class A {
   B instance_of_B; //now compiler's assured that B is a technically "known" type, so it's OK with it.
};

and then at some point later you can "describe" B:

class B {
//blah blah blah
};

Now back to your case:
You have Toast using Person and Person using Toast. These are interleaved and if you do not forward declare at least one, you'll get errors thrown at you by the compiler. Even so, you DO NOT have to forward declare both of them. This is dependent upon your order in which you define Toast and Person. For ex:

Case 1: You define Toast first, then Person.

class Toast {
  //using Person.
};

class Person {
 //using Toast.
};

Here BEFORE Toast the compiler will need to know what Person is so only forward declaration of Person is needed.

class Person;

class Toast {
  //using Person.
};

If you have a class that has no relationship with the others then obviously there is no need to forward declare it. It is only a matter of style that your book is choosing, and it chooses to forward declare everything.

Does that make things much clearer?
class Person {
 //using Toast. Notice now the compiler has already known what Toast is since it's defined/declared ABOVE this.
};

Case 2: You declare Person first, and then Toast.
Now using the same argument you can see that Toast's the only one that needs to be forward declared.

class Toast;

class Person {
 //using Toast.
};

class Toast {
  //using Person.
};

Do
0
 

Author Comment

by:daskino12
ID: 9763901
Hello,

Thank you so much.  It makes sense now.

Thanks

0

Featured Post

Find Ransomware Secrets With All-Source Analysis

Ransomware has become a major concern for organizations; its prevalence has grown due to past successes achieved by threat actors. While each ransomware variant is different, we’ve seen some common tactics and trends used among the authors of the malware.

Join & Write a Comment

Suggested Solutions

Unlike C#, C++ doesn't have native support for sealing classes (so they cannot be sub-classed). At the cost of a virtual base class pointer it is possible to implement a pseudo sealing mechanism The trick is to virtually inherit from a base class…
Many modern programming languages support the concept of a property -- a class member that combines characteristics of both a data member and a method.  These are sometimes called "smart fields" because you can add logic that is applied automaticall…
The viewer will learn additional member functions of the vector class. Specifically, the capacity and swap member functions will be introduced.
The viewer will be introduced to the member functions push_back and pop_back of the vector class. The video will teach the difference between the two as well as how to use each one along with its functionality.

708 members asked questions and received personalized solutions in the past 7 days.

Join the community of 500,000 technology professionals and ask your questions.

Join & Ask a Question

Need Help in Real-Time?

Connect with top rated Experts

16 Experts available now in Live!

Get 1:1 Help Now