friend not allowed outside of a class definition - c++

I'm trying to ovrerload the cout operator in an assignment and I was forced and asked to split my class into (.h and .cpp). Here is my full code:
instructor.h
#include "person.h"
#ifndef instructor_h
#define instructor_h
class instructor: public person {
private:
int children;
int salary;
string maritalStatus;
public:
instructor();
instructor(string, string, string, int , int ,string);
instructor operator++();
void print();
int calcSalary();
int getSalary();
int getNumOfChildren();
string getMarialStatus();
friend ostream &operator <<(ostream, instructor );
void setSalary(int);
void getNumOfChildren(int);
void setMarialStatus(string);
};
#endif
instructor.cpp
#include <iostream>
#include <string>
#include "instructor.h"
using namespace std;
instructor::instructor() {
}
instructor::instructor(string a , string b, string c , int chil , int sal ,string mar):person(a,b,c)
{
children = chil;
salary = sal;
maritalStatus = mar;
}
instructor instructor::operator ++()
{
children=children+1;
return *this;
}
int instructor::calcSalary() {
int new_sal;
new_sal = salary + children*0.1;
return new_sal;
}
int instructor::getSalary() {
cout <<"Here is the result of your query:"<<endl;
cout <<"================================="<<endl;
cout<< "Salary: "<<salary<<""<<endl;
cout <<"================================="<<endl;
cout <<endl;
return salary;
}
int instructor::getNumOfChildren() {
cout <<"Here is the result of your query:"<<endl;
cout <<"================================="<<endl;
cout<< "Number of children: "<<children<<""<<endl;
cout <<"================================="<<endl;
cout <<endl;
return children;
}
string instructor::getMarialStatus() {
cout <<"Here is the result of your query:"<<endl;
cout <<"================================="<<endl;
cout<< "Marital Status: "<<maritalStatus<<""<<endl;
cout <<"================================="<<endl;
cout <<endl;
return maritalStatus;
}
friend ostream& operator<<(ostream& os, instructor& v){
os << v.children;
return os;
}
void instructor::setSalary(int sal) {
salary = sal;
}
void instructor::getNumOfChildren(int nmc) {
children = nmc;
}
void instructor::setMarialStatus(string sms) {
maritalStatus = sms;
}
void instructor::print() {
person::print();
cout <<"Here is the result of your query:"<<endl;
cout <<"================================="<<endl;
cout<< "Marital Status: "<<maritalStatus<<""<<endl;
cout<< "Number of children: "<<children<<""<<endl;
cout<< "Salary: "<<salary<<""<<endl;
cout <<"================================="<<endl;
cout <<endl;
}
I am getting the following errors:
instructor.cpp(75) : error C2255: 'friend' : not allowed outside of a class definition
instructor.cpp(76) : error C2248: 'instructor::children' : cannot
access private member declared in class 'instructor' 1>
c:\documents and settings\george\my documents\visual studio
2005\projects\hana\hana\instructor.h(7) : see declaration of
'instructor::children' 1>
========== Build: 0 succeeded, 1 failed, 0 up-to-date, 0 skipped ==========
I am using visual studio 2005. Why am I getting those errors?
All of this is cause by my attempt in overloading the operator cout:
friend ostream& operator<<(ostream& os, instructor& v){
os << v.children;
return os;
}
Why is not working?

There are two problems. The first is that you can't use friend outside a class, as the error says. But you don't need to; having declared the function as a friend within the class you just define it outside without having to mention the friend-ness again.
But the other problem is that your declaration and definition don't match. You declared this as a friend:
ostream &operator <<(ostream, instructor );
And then you defined this:
ostream& operator<<(ostream&, instructor&)
Those aren't the same, but they need to be.

Related

Why does my code say "Yes" when it should say "No"?

When putting freeSeats to 0, my code still says that a person has avalibale seats in his/hers car.
I have created two classes. One for Car and one for Person. The Car class has a function to see if there are free seats in the car. A person-object can have a car. When checking if the person has avalibale seats, my code responds "Yes" even though I give input "0". Why?
#pragma once
#include <iostream>
//Here is class Car declaration
class Car {
private:
unsigned int freeSeats;
public:
bool hasFreeSeats() const;
void reserveFreeSeat();
Car( unsigned int freeSeats);
};
//Here is function definition
#include "Car.h"
bool Car::hasFreeSeats() const {
if (freeSeats > 0)
return true;
return false;
}
void Car::reserveFreeSeat() {
--freeSeats;
}
Car::Car(unsigned int freeSeas) :
freeSeats{ freeSeats }
{
}
//Here is class Person declaration
class Person {
private:
std::string name;
std::string email;
Car *car; //pointer to a car
public:
Person(std::string name, std::string email, Car *car = nullptr);
std::string getName() const;
std::string getEmail() const;
void setEmail();
bool hasAvalibaleSeats() const;
friend std::ostream& operator << (std::ostream& os, const Person& p);
};
//Here is function definition
Person::Person(std::string name, std::string email, Car *car) :
name{ name }, email{ email }, car{ car }
{
}
std::string Person::getName() const {
return name;
}
std::string Person::getEmail() const {
return email;
}
void Person::setEmail() {
std::string newEmail;
std::cout << "What is the e-mail adress?";
std::cin >> newEmail;
email = newEmail;
std::cout << "E-mail has been set." << std::endl;
}
bool Person::hasAvalibaleSeats() const {
if (car != nullptr) { //check if there is a car
return car->hasFreeSeats();
}
return false;
}
std::ostream& operator << (std::ostream& os, const Person& p) {
std::string seats = "No";
if (p.hasAvalibaleSeats())
seats = "Yes";
return os << "Name: " << p.name << "\nE-mail: " << p.email << "\nHas free seats: " << seats << std::endl;
}
//From main im calling
#include "Car.h"
#include "Person.h"
int main() {
Car ferrari{ 2 };
Car bugatti{ 3 };
Car jeep{0};
Person one{ "Aleksander","aleks#aleks.com", &ferrari };
Person two{ "Sara","sara#sara.com", &bugatti };
Person three{ "Daniel", "daniel#daniel.com", &jeep };
Person four{ "Chris", "chris#chris.com" };
std::cout << one << std::endl;
std::cout << two << std::endl;
std::cout << three << std::endl;
std::cout << four << std::endl;
system("pause");
return 0;
}
I get
Name: Aleksander
E-mail: aleks#aleks.com
Has free seats: Yes
Name: Sara
E-mail: sara#sara.com
Has free seats: Yes
Name: Daniel
E-mail: daniel#daniel.com
Has free seats: Yes
Name: Chris
E-mail: chris#chris.com
Has free seats: No
But I want Daniel has free seats to be "No"
There's a typo here:
Car::Car(unsigned int freeSeas) :
freeSeats{ freeSeats }
{}
You wrote freeSeas instead of freeSeats. Due to that, the freeSeas parameter is unused and freeSeats{ freeSeats } does nothing as freeSeats is refering to the member variable, not the parameter.
Debugging is way easier when you enable compiler warnings. Compiler is your friend, and will help you immensely if you are willing to hear it.
For example, gcc gave me the following warnings when compiling your code:
prog.cc: In constructor 'Car::Car(unsigned int)':
prog.cc:37:23: warning: unused parameter 'freeSeas' [-Wunused-parameter]
Car::Car(unsigned int freeSeas) :
~~~~~~~~~~~~~^~~~~~~~
prog.cc: In constructor 'Car::Car(unsigned int)':
prog.cc:38:16: warning: '*<unknown>.Car::freeSeats' is used uninitialized in this function [-Wuninitialized]
freeSeats{ freeSeats }
^~~~~~~~~
I don't have to understand everything, but it tells me 2 things:
There is unused argument (why? it is used to initialize...)
Variable is initialized with uninitialized value (why?)
It made me look closer at this constructor and then you can see the typo.

Retrieving values of an object from an array?

Pardon the example but in this case:
#include <iostream>
#include <string>
using namespace std;
class A {
private:
string theName;
int theAge;
public:
A() : theName(""), theAge(0) { }
A(string name, int age) : theName(name), theAge(age) { }
};
class B {
private:
A theArray[1];
public:
void set(const A value) {theArray[0] = value; }
A get() const { return theArray[0]; }
};
int main()
{
A man("Bob", 25);
B manPlace;
manPlace.set(man);
cout << manPlace.get();
return 0;
}
Is it possible for me to retrieve the contents of the "man" object in main when I call manPlace.get()? My intention is to print both the name (Bob) and the age (25) when I call manPlace.get(). I want to store an object within an array within another class and I can retrieve the contents of said array within the main.
You need to define a ostream::operator<< on your A class to accomplish that - otherwise the format how age and name should be generated as text-output is undefined (and they are private members of your A class).
Take a look at the reference for ostream::operator<<. For your A class, such a operator could be defined like this:
std::ostream& operator<< (std::ostream &out, A &a) {
out << "Name: " << a.theName << std::endl;
out << "Age: " << a.theAge << std::endl;
return out;
}
Which would output something like:
Name: XX
Age: YY
So your complete code would be:
#include <iostream>
#include <string>
using namespace std;
class A {
private:
string theName;
int theAge;
public:
A() : theName(""), theAge(0) { }
A(string name, int age) : theName(name), theAge(age) { }
friend std::ostream& operator<< (std::ostream &out, A &a) {
out << "Name: " << a.theName << std::endl;
out << "Age: " << a.theAge << std::endl;
return out;
}
};
class B {
private:
A theArray[1];
public:
void set(const A value) { theArray[0] = value; }
A get() const { return theArray[0]; }
};
int main()
{
A man("Bob", 25);
B manPlace;
manPlace.set(man);
cout << manPlace.get();
return 0;
}
which will output:
Name: Bob
Age: 25

Initialize member in print() from another function

Not sure where I am at the moment, trying to figure it out. I need to initialize the members in print() const as it is giving me random gibberish. No matter what I try to do, it does not seem to work. Not sure what to even do. Can anyone give me a hand?
*edit: Added in the rest of the code. Forgot it when I submitted the first time.
Student.cpp
#include "student.h"
//implement the required 3 functions here
Student::Student(const char initId[], double gpa)
{
// initialize a newly created student object with the passed in value
}
bool Student::isLessThanByID(const Student& aStudent) const
{
// compare the current student object with the passed in one by id.
if (strcmp(id, aStudent.id) > 0)
{
return true;
}
else
{
return false;
}
}
bool Student::isLessThanByGpa(const Student& aStudent) const
{
// compare the current student object with the passed in one by gpa
if (gpa < aStudent.gpa)
{
return true;
}
else
{
return false;
}
}
void Student::print() const
{
cout << id << '\t' << gpa << endl;
}
student.h
#ifndef STUDENT_H
#define STUDENT_H
#include <iostream>
using namespace std;
class Student
{
public:
Student(const char initId[], double gpa);
bool isLessThanByID(const Student& aStudent) const;
bool isLessThanByGpa(const Student& aStudent) const;
void print()const;
private:
const static int MAX_CHAR = 100;
char id[MAX_CHAR];
double gpa;
};
#endif
app.cpp
#include "student.h"
int main()
{
Student s1("G10", 3.9);
Student s2("G20", 3.5);
s1.print();
s2.print();
if(s1.isLessThanByID(s2))
{
cout << "about right!" << endl;
}
else
{
cout << "uhmm ..." << endl;
}
if(!s1.isLessThanByGpa(s2))
{
cout << "about right!" << endl;
}
else
{
cout << "uhmm ..." << endl;
}
system("pause");
return 0;
}
There is nothing in that code that sets the values of Student::id and Student::gpa. Your constructor has parameters initId and gpa; you should copy those into your object. Based on the declaration of Student that you provided, something this should be appropriate:
Student::Student(const char initId[], double gpa) : gpa(gpa)
{
strncpy(id, initId, Student::MAX_CHAR-1);
id[Student::MAX_CHAR-1] = '\0';
}

debugging error at the end of the console

I'm a student and I studying c++.
This is my cpp code
int _tmain(int argc, _TCHAR* argv[])
{
CFood output;
output.whatFunc();
cout<<"my outputs"<<endl<<output<<endl;
return 0;
}
ostream& operator <<(ostream& outputStream, const CFood& output)
{
for(int i=0; i<2; i++)
{
outputStream <<"1 : "<<output.m_strName[i]<<" 2 : "<<output.m_servingSize[i]<<"g "<<"3 : "<<
output.m_calorie[i]<<"cal "<<"4 : "<<output.m_transFat[i]<<"g"<<endl;
}
return outputStream;
}
When I debug it, It work. But the end of the console, it gives me error message;;;
It says "An unhandled win32 exception occurred in work.exe [5796]"
My header filed is
class CFood
{
public:
CFood(void);
~CFood(void);
private:
string m_strName[7];
double m_servingSize[7];
double m_calorie[7];
double m_transFat[7];
public:
void whatFunc(void);
friend ostream& operator <<(ostream& outputStream,const CFood& output);
}
I think there is something wrong in my code..And I think it's CFood output;(Just thinking..)
Do you know why it has debug error?
++Sorry, I forgot the whatFunc(void)
This is code
void CFood::whatFunc(void) //
{
m_strName[0]="chicken";
m_strName[1]="rice";
m_strName[2]="meat";
m_strName[3]="strawberry";
m_strName[4]="apple";
m_strName[5]="water";
m_strName[6]="juice";
m_servingSize[0]=10;
m_servingSize[1]=20;
m_servingSize[2]=30;
m_servingSize[3]=40;
m_servingSize[4]=50;
m_servingSize[5]=60;
m_servingSize[6]=70;
m_calorie[0]=10.45;
m_calorie[1]=20.57;
m_calorie[2]=30.78;
m_calorie[3]=40.23;
m_calorie[4]=50.85;
m_calorie[5]=60.73;
m_calorie[6]=70.27;
m_transFat[0]=0.01;
m_transFat[1]=0.02;
m_transFat[2]=0.03;
m_transFat[3]=0.04;
m_transFat[4]=0.05;
m_transFat[5]=0.06;
m_transFat[6]=0.07;
}
Well its difficult to tell what exactly goes wrong without full source code. In my humble opinion, entire source lefts much to be desired. Placing obviously linked data in the bunch of the unlinked arrays with static size is not a very good pattern. Instead try something like that:
#include <iostream>
#include <vector>
#include <string>
#include <ostream>
struct CFoodItem{
std::string m_strName;
double m_servingSize;
double m_calorie;
double m_transFat;
};
class CFood
{
public:
void AddFoodItem(const CFoodItem& cItem);
friend std::ostream& operator <<(std::ostream& outputStream, const CFood& output);
private:
std::vector<CFoodItem> m_vItems;
};
std::ostream& operator <<(std::ostream& outputStream, const CFood& output)
{
for (auto i = output.m_vItems.begin(); i != output.m_vItems.end(); ++i)
{
outputStream << "1 : " << i->m_strName << " 2 : " << i->m_servingSize << "g " << "3 : " <<
i->m_calorie << "cal " << "4 : " << i->m_transFat << "g" << std::endl;
}
return (outputStream);
}
void CFood::AddFoodItem(const CFoodItem& cItem)
{
m_vItems.push_back(cItem);
}
int __cdecl main(void)
{
CFood output;
CFoodItem itm;
itm.m_strName = "some food";
itm.m_servingSize = 100500;
itm.m_calorie = 42;
itm.m_transFat = 42;
output.AddFoodItem(itm);
std::cout << "my outputs" << std::endl << output << std::endl;
return 0;
}

Undefined reference error in c++ dynamic member

hi everyone im new to programming so excuse the noob question...
i tried every method to get through with the undefined refernce error but it keeps throwing that error at me
i tried using pointer "->" and the "::" sign and also the dot "."
what am i supposed to do? why cant it compile?
this is my cpp file:
#include <cstdlib>
#include "account.hpp"
using namespace std;
int Account::getAccountNumber()
{
return accountNumber;
}
double Account::getBalance()
{
return balance;
}
void Account::createAccount(LinkedList<Account>& accountsList, string name, int idNumber)
{
...
case 1:
accountsList.addFront(newAcc); //Where the error occurs.
break;
case 2:
do
{
cout << "\n\tWhich position would you like to insert the\n"
<< "\tnew account into?\n"
<< "\tPosition number: #";
cin >> target;
if (cin.fail())
{
cin.clear();
cin.ignore(20,'\n');
cout << "\n\n\tSorry, wrong input. Please enter a correct position.\n\n";
system("pause");
}
}
while(cin.fail());
accountsList.addMiddle(newAcc, target); //and here
break;
case 3:
accountsList.addEnd(newAcc); //and here
break;
}
cout << "\n\n\tAccount Created Successfully\n\n"
<< accountsList;
system("pause");
}
and here is my .hpp
#ifndef ACCOUNT_HPP_INCLUDED
#define ACCOUNT_HPP_INCLUDED
#include "linkedlist.hpp"
#include "generic.hpp"
class Account : public GenericAccount
{
int accountNumber;
double balance;
public:
Account(string name = "empty", int idNumber = 0, int accountNumber = 0, double balance = 0)
: GenericAccount(name, idNumber), accountNumber(accountNumber), balance(balance) {}
int getAccountNumber();
double getBalance();
void createAccount(LinkedList<Account>&, string, int);
void deposit(LinkedList<Account>&, Account&);
void withdraw(LinkedList<Account>&, Account&);
void displayAccount(LinkedList<Account>&, Account&);
void deleteAccount(LinkedList<Account>&);
friend istream& operator>> (istream& is, Account& x)
{
is >> x.accountNumber;
return is;
}
friend ostream& operator << (ostream& os, Account& c)
{
os << "Account Number= " << c.getAccountNumber() << "\t"
<< "Balance= "<< c.getBalance() << endl;
return os;
}
friend bool operator == (Account& a, Account& target)
{
return (a.getAccountNumber() == target.getAccountNumber());
}
};
#endif // ACCOUNT_HPP_INCLUDED
the full project can be downloaded HERE for refernce
THANK YOU ALL IN ADVANCE!
I think the issue is that there is that the addFront method is not being defined for the account type (in fact any type). See Why can templates only be implemented in the header file? for a much better explanation.
Moving the contents of cpp inline in the .h file should do the trick. Another option is to rename the the .cpp file to a .inl and include it at the bottom of linkedList.hpp