ambiguous error: template C++ - c++

I've tried almost everything imaginable (apart from the right thing of course), but still can't see why I'm getting an ambiguous error. I am fairly certain it's something really silly but I just can't see it! My compiler shows warnings with the insertion operators and I know they're both being called but I was told sticking in the old virtual would help me out there (and it hasn't...), not yet anyway!
#include<iostream>
#include<iomanip>
#include<vector>
#include<string>
#include<algorithm>
using namespace std;
template <class T>
T produceReport(string title, T accType, int tableRows)
{
cout << title << endl;
for (int x = 0; x < tableRows; x++)
{
cout << "-";
}
cout << endl << accType;
};
class BankAccount
{
private:
int accNum;
double accBal;
public:
BankAccount(int = 0, double = 0.0);
void enterAccountData();
void displayAccount();
};
BankAccount::BankAccount(int num, double bal)
{
accNum = num;
accBal = bal;
}
void BankAccount::enterAccountData()
{
cout << setprecision(2) << fixed;
const int MIN_ACC = 1000, MAX_ACC = 9999, DEFAULT = 0;
cout << "Enter account number: ";
cin >> accNum;
if (accNum < MIN_ACC || accNum > MAX_ACC)
accNum = DEFAULT;
cout << "Enter account balance: $";
cin >> accBal;
}
void BankAccount::displayAccount()
{
cout << "Account#" << accNum <<
", Balance: $" << accBal << endl;
}
class SavingsAccount: virtual public BankAccount
{
friend ostream& operator<<(ostream&, SavingsAccount);
protected:
double intRate;
public:
SavingsAccount(double = 0.0);
void getSavAccount();
void displayAccount();
};
SavingsAccount::SavingsAccount(double rate)
{
intRate = rate;
}
void SavingsAccount::getSavAccount()
{
cout << "Enter interest rate: ";
cin >> intRate;
}
ostream& operator<<(ostream& out, SavingsAccount savAcc)
{
savAcc.displayAccount();
return out;
}
void SavingsAccount::displayAccount()
{
BankAccount::displayAccount();
cout << "Interest rate is: " << intRate << endl;
}
class CheckingAccount: virtual public BankAccount
{
friend ostream& operator<<(ostream&, CheckingAccount);
private:
double monthFee;
int numChecks;
public:
CheckingAccount(int = 0, double = 0.0, double = 0.0, int = 0);
void getCheckAccount();
void displayAccount();
};
CheckingAccount::CheckingAccount(int num, double bal, double fee, int check):
BankAccount(num, bal), monthFee(fee), numChecks(check)
{}
void CheckingAccount::getCheckAccount()
{
cout << "Enter monthly fee for account: $";
cin >> monthFee;
cout << "Enter number of checks remaining: ";
cin >> numChecks;
}
ostream& operator<<(ostream& out, CheckingAccount checkAcc)
{
checkAcc.displayAccount();
return out;
}
void CheckingAccount::displayAccount()
{
BankAccount::displayAccount();
cout << "Monthly fee on account is: $" << monthFee << endl;
cout << "Checks remaining for account: " << numChecks << endl << endl;
}
class CheckingAccountWithInterest: public SavingsAccount, public CheckingAccount
{
public:
CheckingAccountWithInterest();
void displayAccount();
};
CheckingAccountWithInterest::CheckingAccountWithInterest():
CheckingAccount(), SavingsAccount()
{}
void CheckingAccountWithInterest::displayAccount()
{
BankAccount::displayAccount();
intRate = 0.02;
SavingsAccount::displayAccount();
CheckingAccount::displayAccount();
}
int main()
{
const int NUM_ACCS = 5;
unsigned count;
vector<SavingsAccount> savAcc;
SavingsAccount aSavAcc;
vector<CheckingAccount> checkAcc;
CheckingAccount aCheckAcc;
vector<CheckingAccountWithInterest> checkAccWithInt;
CheckingAccountWithInterest aCheckAccWithInt;
for (count = 0; count < NUM_ACCS; count++)
{
aSavAcc.enterAccountData();
aSavAcc.getSavAccount();
savAcc.push_back(aSavAcc);
}
for (count = 0; count < NUM_ACCS; count++)
{
aCheckAcc.enterAccountData();
aCheckAcc.getCheckAccount();
checkAcc.push_back(aCheckAcc);
}
for (count = 0; count < NUM_ACCS; count++)
{
aCheckAccWithInt.enterAccountData();
aCheckAccWithInt.getSavAccount();
aCheckAccWithInt.getCheckAccount();
checkAccWithInt.push_back(aCheckAccWithInt);
}
cout << endl;
for (count = 0; count < NUM_ACCS; count++)
{
produceReport("Savings Account Information", savAcc.at(count), 25);
}
for (count = 0; count < NUM_ACCS; count++)
{
produceReport("Checking Account Information", checkAcc.at(count), 25);
}
for (count = 0; count < NUM_ACCS; count++)
{
produceReport("Checking Account With Interest Information", checkAccWithInt.at(count), 30);
}
}
Error is when calling cout << endl << accType;
template <class T>
T produceReport(string title, T accType, int tableRows)
{
cout << title << endl;
for (int x = 0; x < tableRows; x++)
{
cout << "-";
}
cout << endl << accType;
};
ProduceReport.cpp:16: error: ambiguous overload for 'operator<<' in 'std::cout. std::basic_ostream<_CharT, _Traits>::operator<< [with _CharT = char, _Traits = std::char_traits<char>](std::endl [with _CharT = char, _Traits = std::char_traits<char>]) << accType'
is the error message.
Any help or tips are greatly appreciated for how to get past this error!

CheckingAccountWithInterest inherits from two classes. Both of them support an operator<< that is equally likely to be the one that CheckingAccountWithInterest should use. It's irrelevant that they both call displayAccount(); the ambiguity occurs before the compiler ever gets there. You need to sort that ambiguity out.

Related

C++ undefined reference to `findGrossPay(employeeInfo, double, int)'

A class I've been working on for a few days, running into an error I'm unsure how to fix.
#include <iostream> // for cin, cout, endl
#include <string>
#include <iomanip> // formatting floats
using namespace std;
void programHeader();
void footer();
void printEmployeeInfo(struct employeeInfo);
struct employeeInfo
{
int employeeID;
char employeeName[20];
double payRate;
int employeeType;
};
float findGrossPay(employeeInfo myEmployee, double , int);
void payrollDisplay(employeeInfo myEmployee, double, double, double, float, float);
//prototype declerations
int main()
{
// decleration of variables
float inputNumber1;
int num1;
int num2;
int num3;
int num4;
employeeInfo myEmployee[4];
float totalGross;
float totalNet;
int maxName = 20;
int location;
double hoursArray[4];
double grossPay[4];
double tax[4];
double netPay[4];
// input section
programHeader();
num4 = 0;
location = 0;
for (int c = 0; c < 4; c++) // fill in the array of structs
{
while (true); // validation loop
{
cout << "Employee ID: ";
cin >> num1;
if (num1 > 0);
{
myEmployee[c].employeeID = num1;
break;
} // end if
if (num1 <= 0)
{
cout << "\nERROR PLEASE TRY AGAIN" << endl;
} // end else if
} // end while
cout << "Employee Name: ";
cin.getline(myEmployee[c].employeeName, maxName);
while (true); // validation loop
{
cout << "Pay rate: ";
cin >> num2;
if (num2 > 0);
{
myEmployee[c].payRate = num2;
break;
} // end if
if (num2 <= 0)
{
cout << "\nERROR PLEASE TRY AGAIN" << endl;
} // end if
} // end while
while (true) // validation loop
{
cout << "Type: ";
cin >> num3;
if ((num3 == 1) || (num3 == 0))
{
myEmployee[c].employeeType = num3;
break;
} // end if
else
{
cout << "\nERROR PLEASE TRY AGAIN" << endl;
} // end else
} // end while
} // end for(c)
for (int h = 0; h < 4; h++); // parallel array to hold hours worked
{
cout << "Hours worked for " << myEmployee[num4].employeeName << ": ";
cin >> hoursArray[num4];
num4 = num4 +1;
} // end for(h)
// calculation section
// displays the results
for (int l = 0; l < 4; l++) // l for location
{
grossPay[l] = findGrossPay(myEmployee[4], hoursArray[4], location);
location = location + 1;
} // end for(l)
for (int t = 0; t < 4; t++) // get taxes and net pay for each
{
tax[t] = grossPay[t] * (15 / 100);
netPay[t] = grossPay[t] - tax[t];
}
for (int i = 0; i < 4; i++)
{
totalGross = totalGross + grossPay[i];
totalNet = totalNet + netPay[i];
} // end of for
payrollDisplay(myEmployee[4], grossPay[4], tax[4], netPay[4], totalGross, totalNet);
footer();
system("PAUSE");
return 0;
}// end of main
float findGrossPay(employeeInfo myEmployee[4], double hoursArray[4], int l) // l stands for location
{
float numGrossPay;
if (myEmployee[l].employeeType == 1) // management
{
numGrossPay = myEmployee[l].payRate * hoursArray[l];
} // end if
else if (myEmployee[l].employeeType == 0) // union members
{
if (hoursArray[l] > 40)
{
numGrossPay = myEmployee[l].payRate * 40 + (hoursArray[l] - 40) * (myEmployee[l].payRate * 1.5);
} // end if
else
{
numGrossPay = myEmployee[l].payRate * hoursArray[l];
} // end else
} // end else if
return numGrossPay;
}
void payrollDisplay(employeeInfo myEmployee[4], double grossPay[4], double tax[4], double netPay[4], float totalGross, float totalNet)
{
cout << "------------------------------------------------------------" << endl;
cout << "\nPayroll Report\n" << endl;
cout << "ID \tName" << "\t\tGross Pay \tTax \tNet Pay" << endl;
for (int i = 0; i < 4; i++) // to print each employee
{
cout << myEmployee[i].employeeID << "\t" << myEmployee[i].employeeName << "\t\t" << grossPay[i]
<< "\t" << tax[i] << "\t" << netPay[i] << endl;
} // for(i)
cout << "\nTotal Gross Pay \t$" << totalGross << endl;
cout << "Total Net Pay \t$" << totalNet << endl;
}
It's giving me an error stating there is an undefined reference to these lines in main():
grossPay[l] = findGrossPay(myEmployee[4], hoursArray[4], location);
and
payrollDisplay(myEmployee[4], grossPay[4], tax[4], netPay[4], totalGross, totalNet);
The "undefined reference" errors are because your function declarations do not match their definitions.
You have declared findGrossPay() and payrollDisplay() as taking in a single employeeInfo and related values for that one employee, but then your definitions are taking in arrays of employees and values:
//declaration
float findGrossPay(employeeInfo myEmployee, double , int);
//definition
float findGrossPay(employeeInfo myEmployee[4], double hoursArray[4], int l)
// declaration
void payrollDisplay(employeeInfo myEmployee, double, double, double, float, float);
//definition
void payrollDisplay(employeeInfo myEmployee[4], double grossPay[4], double tax[4], double netPay[4], float totalGross, float totalNet)
As such, the linker can't find matching definitions for the functions you are actually calling.
And, to make that worse, the places where you are calling these functions are accessing array elements out of bounds, which is undefined behavior.
After you fix that problem, you should then get "undefined reference" errors for programHeader() and footer(), since their definitions are missing completely.
After fixing that, there are still other problems with your code:
you have a number of if and for/while loops that have an erroneous ; on them
you are accessing arrays incorrectly in some places
you have uninitialized variables in some of your calculations
With that said, try something more like this:
#include <iostream> // for cin, cout, endl
#include <string>
#include <iomanip> // formatting floats
#include <limits>
using namespace std;
struct employeeInfo
{
int employeeID;
string employeeName;
double payRate;
int employeeType;
};
//prototype declerations
void programHeader();
void footer();
int promptForNumber(const string &prompt, int minValue = 0, int maxValue = numeric_limits<int>::max());
string promptForString(const string &prompt);
float findGrossPay(const employeeInfo &myEmployee, double hours);
void payrollDisplay(const employeeInfo myEmployee[4], const double grossPay[4], const double tax[4], const double netPay[4]);
int main()
{
// decleration of variables
employeeInfo myEmployee[4];
double hours[4];
double grossPay[4];
double tax[4];
double netPay[4];
int num;
// input section
programHeader();
for (int c = 0; c < 4; c++) // fill in the array of structs
{
myEmployee[c].employeeID = promptForNumber("Employee ID", 1);
myEmployee[c].employeeName = promptForString("Employee Name");
myEmployee[c].payRate = promptForNumber("Pay rate", 1);
myEmployee[c].employeeType = promptForNumber("Type", 0, 1);
}
for (int h = 0; h < 4; h++) // parallel array to hold hours worked
{
hours[h] = promptForNumber("Hours worked for " << myEmployee[h].employeeName);
}
// calculation section
for (int l = 0; l < 4; l++) // l for location
{
grossPay[l] = findGrossPay(myEmployee[l], hours[l]);
}
for (int t = 0; t < 4; t++) // get taxes and net pay for each
{
tax[t] = grossPay[t] * (15 / 100);
netPay[t] = grossPay[t] - tax[t];
}
// displays the results
payrollDisplay(myEmployee, grossPay, tax, netPay);
footer();
system("PAUSE");
return 0;
}
void programHeader()
{
// print out something here...
}
void footer()
{
// print out something here...
}
int promptForNumber(const string &prompt, int minValue, int maxValue)
{
int num;
while (true) // validation loop
{
cout << prompt << ": ";
if (cin >> num)
{
cin.ignore(numeric_limits<streamsize>::max(), '\n');
if ((num >= minValue && num <= maxValue)
break;
}
else
{
cin.clear();
cin.ignore(numeric_limits<streamsize>::max(), '\n');
}
cout << "\nERROR PLEASE TRY AGAIN" << endl;
}
return num;
}
string promptForString(const string &prompt)
{
string input;
while (true) // validation loop
{
cout << prompt << ": ";
if (getline(cin, input) && !input.empty())
break;
cout << "\nERROR PLEASE TRY AGAIN" << endl;
}
return input;
}
float findGrossPay(const employeeInfo &myEmployee, double hours)
{
if (myEmployee.employeeType == 1) // management
{
return myEmployee.payRate * hours;
}
// must be myEmployee.employeeType == 0 // union members
if (hours > 40)
{
return myEmployee.payRate * 40 + (hours - 40) * (myEmployee.payRate * 1.5);
}
else
{
return myEmployee.payRate * hours;
}
}
void payrollDisplay(const employeeInfo myEmployee[4], const double grossPay[4], const double tax[4], const double netPay[4])
{
float totalGross = 0.0f;
float totalNet = 0.0f;
cout << "------------------------------------------------------------" << endl;
cout << "\nPayroll Report\n" << endl;
cout << "ID \tName" << "\t\tGross Pay \tTax \tNet Pay" << endl;
for (int i = 0; i < 4; i++) // to print each employee
{
cout << myEmployee[i].employeeID << "\t" << myEmployee[i].employeeName << "\t\t" << grossPay[i] << "\t" << tax[i] << "\t" << netPay[i] << endl;
totalGross += grossPay[i];
totalNet += netPay[i];
}
cout << "\nTotal Gross Pay \t$" << totalGross << endl;
cout << "Total Net Pay \t$" << totalNet << endl;
}
That said, you might consider moving the hours/grossPay/tax/netPay values into the employeeInfo struct, so that you have to manage only 1 array and not 5 parallel arrays.

exception unhandled violation access

I was using a dynamic array to expand it in the function assignbook and I have no idea why when I delete[] the array it gives me unhandled access violation.
this is the main
int main() {
Translator t;
Book b;
t.AssignBook(b);
t.AssignBook(b);
t.AssignBook(b);
t.AssignBook(b);
t.AssignBook(b);
t.AssignBook(b);
t.AssignBook(b);
t.AssignBook(b);
t.AssignBook(b);
t.AssignBook(b);
t.AssignBook(b);
t.AssignBook(b);
cout << t.getNumBooks();
}
and this is the implementation of translator class :
void Translator::AssignBook(Book& x) {
if (numBooks < size) {
translatebooks[numBooks] = x;
numBooks++;
}
else {
size += 10;
Book* t = new Book[size];
for (int i = 0; i < numBooks; i++) {
t[i] = translatebooks[i];
}
delete[] translatebooks;
translatebooks = t;
translatebooks[numBooks] = x;
cout << "The array is too small so it expanded from size " << numBooks << " to " << size << endl;
numBooks++;
}
}
and this is the error:
I'm so done with this error, please help. I do delete the array again in the destructor, though.
When I remove the delete[] statement it works, but still it gives me the weird accesss thing. :/
there's the whole code :
#include<iostream>
#include<string>
#define size1 2
using namespace std;
class Date {
private:
int Day;
int Month;
int Year;
public:
Date();
Date(int, int, int);
int getDay() const;
int getMonth() const;
int getYear() const;
void setDate(int, int, int);
void setMonth(int);
void setYear(int);
void setDay(int);
void print() const;
};
class Person {
private :
int PID;
string Pname;
public :
Person();
Person(int, string);
int getPID() const;
string getPname() const;
void setPID(int);
void setPerson(int, string);
void setPname(string);
void print() const;
};
class Book {
private:
int ISBN;
string BookTitle;
int NumPages;
string Language;
Date PublishingDate;
int NumAuthors;
Person* Authors;
public:
Book();
Book(int, string, int, string, Date&, int);
~Book();
void setISBN(int);
void setBookTitle(string);
void setLanguage(string);
void setNumPages(int);
void setPublishDate(Date&);
void setNumberAuthors(int);
void setAuthor(Person&);
int getISBN() const;
string getBookTitle() const;
string getLanguage() const;
int getNumPages() const;
Date getPublishDate() const;
int getNumberAuthors() const;
void print() const;
};
class Employee {
private:
Person Ename;
double salary;
protected:
int Rank;
public:
Employee();
Employee(Person&, double ,int);
void setEname(Person&);
void setSalary(double);
void setRank(int);
Person getEname() const;
int getRank() const;
virtual bool isManager() ;
virtual double getNetSalary();
double getSalary() const;
void print() const;
virtual void AssignBook(Book&);
};
class Translator:public Employee{
private:
int Experience;
int numBooks;
Book *translatebooks;
int size;
public :
void setExperience(int);
void AssignBook(Book&);
void unAssignBook(int ISBN);
double getNetSalary() const;
int getExperience() const;
int getNumBooks() const;
Translator();
Translator(Person&, double, int,int);
~Translator();
bool isManager();
void print() const;
};
class Manager : public Employee {
private:
bool certified;
public :
void setCertified(bool x);
bool getCertified();
Manager();
Manager(Person&, double, int,bool);
~Manager();
bool isManager();
};
Employee* ReadOneEmployee() {
int x;
cout << "Please Enter 1 for Translator \n 2 for Manager\n";
cin >> x;
if (x == 1) {
cout << "Name :" << endl;
string name;
cin >> name;
cout << "Rank: \n";
int Rank;
cin >> Rank;
cout << "Experience\n";
int Experience;
cin >> Experience;
cout << "Salary \n";
double salary;
cin >> salary;
cout << "ID =\n";
int ID;
cin >> ID;
Person P(ID, name);
return new Translator(P, salary, Rank, Experience);
}
else if (x == 2) {
cout << "Name :" << endl;
string name;
cin >> name;
cout << "Rank: \n";
int Rank;
cin >> Rank;
cout << "Certified:\n";
bool Experience;
cin >> Experience;
cout << "Salary \n";
double salary;
cin >> salary;
cout << "ID =\n";
int ID;
cin >> ID;
Person P(ID, name);
return new Manager(P, salary, Rank, Experience);
}
}
double Tax = 0.2;
int main() {
Book books[200];
Person z(2,"Meh");
Person x(2, "xd");
books[0].setAuthor(z);
books[0].setAuthor(x);
books[0].setNumPages(5);
Employee *list[size1];
for (int i = 0; i < size1; i++) {
list[i] = ReadOneEmployee();
}
int booksnum = 123;
int i = 0;
while (booksnum >= 0) {
if (!list[i]->isManager() && i<size1) {
list[i]->AssignBook(books[booksnum]);
i++;
}
else if (i >= size1) {
i = 0;
}
booksnum--;
}
for (int i = 0; i < size1; i++) {
cout << "Name :" << list[i]->getEname().getPname() << endl;
cout << "Salary =" << list[i]->getSalary() << endl;
cout << "Net Salary =" << list[i]->getNetSalary() << endl;
}
double totalN = 0,totalS=0;
for (int i = 0; i < size1; i++) {
totalN += list[i]->getNetSalary();
totalS += list[i]->getSalary();
}
cout << "Total Salary is :" << totalS << endl;
cout << "Total Net Salary is :" << totalN << endl;
int totalP = 0;
for (int i = 0; i < 200; i++) {
totalP += books[i].getNumPages();
}
cout << "Total Pages is :" << totalP << endl;
int max = 0;
for (int i = 0; i < 200; i++) {
if (books[i].getNumberAuthors() > max) {
max = books[i].getNumberAuthors();
}
}
for (int i = 0; i < 200; i++) {
if (books[i].getNumberAuthors() == max) {
books[i].print();
}
}
}
//i used regions to make it easier to read!
#pragma region Date_Implementation
Date::Date() {
Day = Month = 1;
Year = 1900;
}
Date::Date(int x,int y,int z) {
setDate(x, y, z);
}
int Date::getDay() const {
return Day;
}
int Date::getMonth() const {
return Month;
}
int Date::getYear() const {
return Year;
}
void Date::setDate(int x, int y, int z) {
setDay(x);
setMonth(y);
setYear(z);
}
void Date::setMonth(int x) {
if (x > 0 && x <= 12) {
Month = x;
}
else {
cout << "Invalid Value for the Months and it's been set to 1\n";
Month = 1;
}
}
void Date::setYear(int x){
if (x >= 1900) {
Year = x;
}
else {
cout << "Invalid Value for the Years and it's been set to 1900\n";
Year = 1900;
}
}
void Date::setDay(int x) {
if (x > 0 && x <= 31) {
Day = x;
}
else {
cout << "Invalid Value for the Days and it's been set to 1\n";
Day = 1;
}
}
void Date::print() const {
cout << "The Date is: " << Day << "/" << Month << "/" << Year << endl;
}
#pragma endregion
#pragma region Person_Implemntation
Person::Person() {
Pname = "";
PID = 1;
}
Person::Person(int x, string y) {
setPerson(x, y);
}
void Person ::setPerson(int x, string y) {
setPname(y);
setPID(x);
}
int Person::getPID() const {
return PID;
}
string Person::getPname() const {
return Pname;
}
void Person::setPID(int x) {
if (x > 0) {
PID = x;
}
else {
cout << "Invalid Value for PID it's been set to 1\n";
PID = 1;
}
}
void Person::setPname(string x) {
if (x != "") {
Pname = x;
}
else {
cout << "Invalid Value for Pname it's been set to \"\"\n";
Pname="";
}
}
void Person::print() const {
cout << "Person's name = " << Pname << endl;
cout << "Person's ID = " << PID << endl;
}
#pragma endregion
#pragma region Book_Implementation
Book::Book() {
ISBN = NumPages = 1;
Authors = new Person[3];
BookTitle = "";
Language = "English";
NumAuthors = 0;
PublishingDate.setDate(1, 1, 1900);
}
Book::Book(int x, string y, int z, string c, Date& v, int b) {
setISBN(x);
setBookTitle(y);
setNumPages(z);
setLanguage(c);
setPublishDate(v);
NumAuthors = 0;
}
Book::~Book() {
// cout << "Book " << BookTitle << " Destructed\n";
delete[] Authors;
}
void Book::setISBN(int x) {
if (x > 0) {
ISBN = x;
}
else {
cout << "Invalid Value for ISBN it's been set to 1\n";
ISBN = 1;
}
}
void Book::setBookTitle(string x) {
if (x != "") {
BookTitle = x;
}
else {
cout << "Invalid value for Book title it's been set to \"\"\n";
BookTitle = "";
}
}
void Book::setLanguage(string x) {
if (x == "English" ||x=="Arabic") {
BookTitle = x;
}
else {
cout << "Invalid value for Book's Language it's been set to English\n";
BookTitle = "English";
}
}
void Book::setNumPages(int x) {
if (x > 0) {
NumPages = x;
}
else {
cout << "Invalid Value for Number of Pages it's been set to 1\n";
NumPages = 1;
}
}
void Book::setPublishDate(Date& x) {
PublishingDate.setDate(x.getDay(), x.getMonth(), x.getYear());
}
void Book::setNumberAuthors(int x) {
if (x > 0 && x<=3) {
NumAuthors = x;
}
else {
cout << "Invalid Value for Number of authors it's been set to 1\n";
NumAuthors = 1;
}
}
void Book::setAuthor(Person& x) {
if (NumAuthors < 3) {
Authors[NumAuthors].setPerson(x.getPID(), x.getPname());
NumAuthors++;
}
else cout << "Can't set an author cause the array is full!!\n";
}
int Book::getISBN() const {
return ISBN;
}
string Book::getBookTitle() const {
return BookTitle;
}
int Book::getNumPages() const {
return NumPages;
}
Date Book::getPublishDate() const {
return PublishingDate;
}
int Book::getNumberAuthors() const {
return NumAuthors;
}
string Book::getLanguage() const {
return Language;
}
void Book::print() const {
cout << "ISBN = " << ISBN << endl;
cout << "BookTitle = " << BookTitle << endl;
cout << "Number of Pages = " << NumPages << endl;
cout << "Language = " << Language << endl;
cout << "The Authors that were set :\n";
for (int i = 0; i < NumAuthors; i++) {
Authors[i].print();
}
}
#pragma endregion
#pragma region Employee_Implementation
Employee::Employee() {
Rank = salary = 0;
Ename.setPerson(1, "Default");
}
Employee::Employee(Person& x, double y, int z) {
setEname(x);
setRank(z);
setSalary(y);
}
void Employee::setEname(Person& x) {
Ename.setPerson(x.getPID(), x.getPname());
}
void Employee::setSalary(double x) {
if (x > 0) {
salary = x;
}
else {
cout << "Invalid Value for Salary it's been set to 0\n";
salary = 0;
}
}
void Employee::setRank(int x) {
if (x >= 0) {
Rank = x;
}
else {
cout << "Invalid Value for Rank it's been set to 0\n";
Rank = 0;
}
}
Person Employee::getEname() const {
return Ename;
}
int Employee::getRank() const {
return Rank;
}
double Employee::getSalary() const {
return salary;
}
double Employee::getNetSalary() {
double totalS = salary + (Rank * 320);
double Net_Salary = totalS - totalS * Tax;
return Net_Salary;
}
void Employee::print() const {
Ename.print();
cout << "Rank = " << Rank<<endl;
cout << "salary = " << salary << endl;
}
bool Employee :: isManager() {
return false;
}
void Employee::AssignBook(Book& x) {
cout << "Can't cause it's just an Employee!";
}
#pragma endregion
#pragma region Translator_Implementation
void Translator::setExperience(int x) {
if (x >= 0) {
Experience = x;
}
else
{
cout << "Invalid Value for The Experience it's been set to 0\n";
Experience = 0;
}
}
void Translator::AssignBook(Book& x) {
if (numBooks < size) {
translatebooks[numBooks] = x;
numBooks++;
}
else {
size += 10;
Book* t = new Book[size];
for (int i = 0; i < numBooks; i++) {
t[i] = translatebooks[i];
}
delete[] translatebooks;
translatebooks = t;
translatebooks[numBooks] = x;
cout << "The array is too small so it expanded from size " << numBooks << " to " << size << endl;
numBooks++;
}
}
void Translator::unAssignBook(int ISBN) {
for (int i = 0; i < numBooks; i++) {
if (translatebooks[i].getISBN() == ISBN) {
for (int j = i; j < numBooks-1; j++) {
translatebooks[j] = translatebooks[j + 1];
}
numBooks--;
break;
}
}
}
double Translator::getNetSalary() const {
int total = 1;
for (int i = 0; i < numBooks; i++) {
total += translatebooks[i].getNumPages();
}
return getNetSalary() + 5 * total;
}
int Translator::getExperience() const {
return Experience;
}
int Translator::getNumBooks() const {
return numBooks;
}
Translator::Translator():Employee() {
Experience = 0;
numBooks = 0;
size = 10;
translatebooks = new Book[size];
}
Translator::Translator(Person& x, double y, int z, int c) :Employee(x, y, z) {
setExperience(c);
numBooks = 0;
size = 10;
translatebooks = new Book[size];
}
Translator::~Translator() {
delete[] translatebooks;
translatebooks = NULL;
}
bool Translator:: isManager() {
return false;
}
void Translator::print() const{
Employee::print();
cout << "Experience = " << Experience << endl;
cout << "Number of books = " << numBooks << endl;
cout << "And they are :\n";
if (numBooks == 0) cout << "None\n";
else
for (int i = 0; i < numBooks; i++) {
translatebooks[i].print();
}
}
#pragma endregion
#pragma region Manger_Implementation
void Manager::setCertified(bool x) {
certified = x;
}
bool Manager::getCertified() {
return certified;
}
Manager::Manager():Employee() {
certified = false;
}
Manager::Manager(Person& x, double y , int z, bool c):Employee(x,y,z) {
certified = c;
}
Manager::~Manager() {
cout << "Manager Destructed\n";
}
bool Manager::isManager() {
return true;
}
#pragma endregion
You have a rule of 0/3/5 violation. You have no copy constructor for Book. So when your code does:
for (int i = 0; i < numBooks; i++) {
t[i] = translatebooks[i];
}
This invokes the default copy constructor for Book. This is a disaster because the destructor looks like this:
Book::~Book() {
// cout << "Book " << BookTitle << " Destructed\n";
delete[] Authors;
}
So the default copy constructor gives both Book objects the same value for Authors. Whichever one is destroyed first deletes it. That leaves the other one with a pointer to nowhere.
Then this code runs when you expand the array:
delete[] translatebooks;
This destroys the books you copied, destroying the Authors arrays in the copies.
Moral: Don't use raw pointers. Don't use raw arrays. We have lots of classes that make all this stuff easy, why make it hard?

I'm trying to make a static member in my class but compiler is giving me warning that it is undefined

I'm trying to make a static member in my class but compiler is giving me Error that SubjectList::X is undefined . What I'm trying to do is that , I'll make list of 2 subject . And then i gonna ask from student to choose from those two subjects. So i want to make them class property instead of object property. Because if i will not make it static every student gonna ask for subject name and code of its own.
#include <iostream>
#include <string.h>
using namespace std;
class Subject{
public:
friend class SubjectList;
//Subject() {}
Subject(){
cout << "Enter Subject name - ";
cin >> name;
cout << "Enter subject code - ";
cin >> code;
}
private:
int code;
string name;
};
class SubjectValue{
friend class SubjectList;
int value;
};
class SubjectList{
public:
friend class Student;
static Subject X[2]; // HERE IT GIVES ERROR.
SubjectValue sv[2];
set_subject();
show_subject();
};
class Student{
public:
friend class StudentList;
SubjectList sub;
private:
unsigned long int roll;
unsigned long long int phone;
string name;
};
class StudentList{
public:
Student s[2];
set_data();
show_data();
};
StudentList::set_data()
{
int i ;
for(i = 0; i < 2; i++){
cout << "Enter student name - ";
cin >> s[i].name;
cout << "Enter student phone - ";
cin >> s[i].phone;
cout << "Enter roll - ";
cin >> s[i].roll;
s[i].sub.set_subject();
}
}
StudentList::show_data()
{
int i;
for(i = 0; i < 2; i++){
cout << "Name of Student - " << s[i].name << endl;
cout << "Phone of Student - " << s[i].phone << endl;
cout << "Roll of Student - " << s[i].roll << endl;
s[i].sub.show_subject();
}
}
SubjectList::set_subject()
{
int i;
int value[2];
cout << "Enter 1 for the subject you want to choose. \n";
//cout << "Subject " << (i+1);
for(i = 0; i < 2; i++)
{
cin >> value[i];
}
for(i = 0; i < 2; i++)
{
sv[i].value = value[i];
}
}
SubjectList::show_subject()
{
int i;
cout << "Subjects choose by student are - " << endl;
for(i = 0; i < 2; i++)
{
if (sv[i].value == 1)
{
cout << X[i].name << endl;
}
}
}
int main()
{
StudentList s;
s.set_data();
s.show_data();
return 0;
}
You should define SubjectList::X somewhere below the declaration.
class SubjectList {
static Subject X[2];
};
Subject SubjectList::X[2];
If C++17 is available you can use inline keyword.
class SubjectList {
inline static Subject X[2];
};
Detailed explanation : https://en.cppreference.com/w/cpp/language/static

C++ Sort class array using qsort

C++:
I'm trying to sort some students that are stored in a class by average media.
Only qsort, don't advice me of std::sort, thank you!
Qsort compare function:
int cmp(Student *a, Student *b) {
return (int)(((Student *)b)->get_media() - ((Student *)a)->get_media());
}
qsort call:
qsort(&tab, (size_t)n, sizeof(tab), (int(*)(const void*, const void*))cmp);
There's no compiler error, but it won't sort.
#define _CRT_SECURE_NO_WARNINGS
#include <iostream>
using namespace std;
class Student {
private:
char name[20];
char surname[20];
int *marks;
int group;
float avg_mark;
public:
Student()
{
char na[20], sur[20];
int group;
cout << "\nEnter name: ";
cin >> na;
cout << "\nEnter surname: ";
cin >> sur;
cout << "\nEnter group: ";
cin >> group;
init(na, sur, group);
}
~Student()
{
cout << "\ndestructor";
delete []marks;
}
void init(char *n, char *p, int gr)
{
strcpy(name, n);
strcpy(surname, p);
group = gr;
marks = new int[6];
for (int i = 0; i < 6; i++)
{
cout << "\nEnter mark " << i + 1 << ": ";
cin >> *(marks + i);
}
avg_mark = media();
}
float media()
{
int s = 0;
for (int i = 0; i < 6; i++)
s += marks[i];
return ((float)s / 6);
}
void set_name(char *n)
{
strcpy(name, n);
}
char* get_name()
{
return name;
}
void set_surname(char *p)
{
strcpy(name, p);
}
char* get_surname()
{
return surname;
}
int get_group()
{
return group;
}
float get_media()
{
return avg_mark;
}
};
int cmp(Student *a, Student *b);
int comparator(void *a, void *b) {
return (int)(((Student *)b)->get_media() - ((Student *)a)->get_media());
}
void main(void)
{
int n;
cout << "\nEnter n: ";
cin >> n;
Student *tab = new Student[n];
for (int i = 0; i < n; i++)
cout << i + 1 << ". " << tab[i].get_name() << " " << tab[i].get_surname() << " Group:" << tab[i].get_group() << " Average mark: " << tab[i].get_media() << endl;
//qsort(&tab[0], (size_t)n, sizeof(tab), (int*)cmp);
cout << endl;
qsort(&tab, (size_t)n, sizeof(tab), (int(*)(const void*, const void*))cmp);
for (int i = 0; i < n; i++)
cout << i + 1 << ". " << tab[i].get_name() << " " << tab[i].get_surname() << " Group:" << tab[i].get_group() << " Average mark: " << tab[i].get_media() << endl;
cin.ignore();
cin.get();
}
int cmp(Student *a, Student *b) {
return (int)(((Student *)b)->get_media() - ((Student *)a)->get_media());
}
qsort(&tab, (size_t)n, sizeof(tab), (int(*)(const void*, const void*))cmp);
&tab is the address of the pointer tab. You want to pass the address of the first element of your array. That's &tab[0] or simply tab.
Also, you need to pass the size of a Student object, not the size of a pointer. So change sizeof(tab) to sizeof(Student) or sizeof(*tab). So the call should look like this:
qsort(tab, (size_t)n, sizeof(*tab), (int(*)(const void*, const void*))cmp);

for loop character printing [closed]

It's difficult to tell what is being asked here. This question is ambiguous, vague, incomplete, overly broad, or rhetorical and cannot be reasonably answered in its current form. For help clarifying this question so that it can be reopened, visit the help center.
Closed 11 years ago.
.....................HEY GUYS,I GOT THE ANSWER.PLEASE CHECK OUT AT BOTTOM.....................
ThAnKs FoR aLl ThOsE wHo TrYiNg tO hElP mE!
How to print all the character outside the for-loop that input inside for-loop? It only prints the last character entered in for-loop
input all 4 names of items and price in void shop::getdata()
output of this only prints the name of item that entered last in void shop::getdata() for 4 times in void shop::putdata()
output of price is correct,it prints orderly.
what's the problem with the name of item?
Question:WAP to store pricelist of 5 items & print the largest price as well as the sum of all prices & pricelist also.
#include<iostream.h>
#include<conio.h>
#include<string.h>
class shop
{
int i;
char item[50];
float price[50];
public:
void getdata();
void putdata();
float sum();
float lar();
};
void shop::getdata()
{
for(i = 0; i <= 4; i++)
{
cout << "Enter the item name:" << "\n";
cin >> item;
cout << "Enter price:" << "\n";
cin >> price[i];
}
}
void shop::putdata()
{
cout << "\t\tPRICE LIST" << "\n";
cout << "\t\t**********" << "\n";
cout << "ITEM NAME\t\t\tPRICE" << "\n";
cout << "*********\t\t\t*****" << "\n";
for(i = 0; i <= 4; i++)
{
cout << item << "\t\t\t\t";
cout << price[i] << "\n";
}
}
float shop::sum()
{
float sum = 0;
for( i= 0; i <= 4; i++)
{
sum = sum + price[i];
}
cout << "\t\t\t\tsum is:" << sum << "\n";
return sum;
}
float shop::lar()
{
float lar;
lar = price[0];
for(i = 0; i <= 4; i++)
{
if (price[i] > lar)
lar = price[i];
}
cout << "\t\t\tlargest is:" << lar;
return lar;
}
void main()
{
shop x;
int c;
clrscr();
x.getdata();
do
{
cout << "\n\n1.PRICE LIST\n";
cout << "2.SUM\n";
cout << "3.LARGEST\n";
cout << "4.EXIT\n";
cout << "Enter your choice\n";
cin >> c;
switch (c)
{
case 1:
x.putdata();
break;
case 2:
x.sum();
break;
case 3:
x.lar();
break;
default:
cout << "PRESS ANY KEY TO EXIT\n";
break;
}
}
while(c >= 1 && c <= 3);
getch();
}
ANSWER
#include<iostream.h>
#include<conio.h>
#include<string.h>
class shop
{
int i;
char item[50];
float price;
float e[10];
public:
void getdata();
void putdata();
float sum();
float lar();
};
void shop::getdata()
{
cout << "Enter the item name:" << "\n";
cin >> item;
cout << "Enter price:" << "\n";
cin >> price;
}
void shop::putdata()
{
cout << item << "\t\t\t\t";
cout << price << "\n";
}
float shop::sum()
{
float sum = 0;
for( i= 0; i <= 4; i++)
{
cout<<"Enter prices"<<"\n";
cin>>e[i];
sum = sum + e[i];
}
cout << "\t\t\t\tsum is:" << sum << "\n";
return sum;
}
float shop::lar()
{
float lar;
lar = e[0];
for(i = 0; i <= 4; i++)
{
if (e[i] > lar)
lar = e[i];
}
cout << "\t\t\tlargest is:" << lar;
return lar;
}
void main()
{
shop x[10];
int c,i;
clrscr();
for(i=0;i<=4;i++)
x[i].getdata();
do
{
cout << "\n\n1.PRICE LIST\n";
cout << "2.SUM\n";
cout << "3.LARGEST\n";
cout << "4.EXIT\n";
cout << "Enter your choice\n";
cin >> c;
switch (c)
{
case 1:
for(i=0;i<=4;i++)
x[i].putdata();
break;
case 2:
x[i].sum();
break;
case 3:
x[i].lar();
break;
default:
cout << "PRESS ANY KEY TO EXIT\n";
break;
}
}
while(c >= 1 && c <= 3);
getch();
}
It's a little hard to tell what you're asking (you would do well to indent your code and ask a clearer question), but I think your problem (well, the main one you're referring to!) is how you're handling item names.
You've declared your shop to contain an array of 50 chars - that is, 50 single characters. Since you have an array of 50 prices, you almost certainly wanted an array of 50 strings. In basic C, that would be char *item[50], an array of 50 dynamically-allocated char arrays. Since you've tagged this as C++, though, you're better off using a string.
A slightly more modern shop would look like this:
#include <iostream>
#include <string>
#include <vector>
using std::cin;
using std::cout;
using std::ostream;
using std::string;
using std::vector;
class Item {
string m_name;
double m_price;
public:
Item(const string &name, double price)
: m_name(name), m_price(price) {
};
string name() const { return m_name; }
double price() const { return m_price; }
};
class Shop {
vector<Item> m_items;
public:
void readData();
void writeData() const;
double getPriceSum() const;
double getMaxPrice() const;
};
void Shop::readData() {
for (;;) {
string name, end_of_line;
double price;
cout << "Enter the item name (or nothing to finish input): ";
getline(cin, name);
if (name == "") {
break;
}
cout << "Enter the price: ";
cin >> price;
// the previous ">>" left the end-of-line in the stream,
// so read it now.
getline(cin, end_of_line);
m_items.push_back(Item(name, price));
}
}
void Shop::writeData() const {
for (size_t i = 0; i < m_items.size(); i++) {
const Item &item = m_items[i];
cout << item.name() << "\t" << item.price() << "\n";
}
}
double Shop::getPriceSum() const {
double sum = 0.0;
for (size_t i = 0; i < m_items.size(); i++) {
sum += m_items[i].price();
}
return sum;
}
double Shop::getMaxPrice() const {
double max = 0.0; // assume that all prices are positive
for (size_t i = 0; i < m_items.size(); i++) {
max = std::max(max, m_items[i].price());
}
return max;
}
int main() {
Shop shop;
shop.readData();
shop.writeData();
cout << "sum: " << shop.getPriceSum() << "\n";
cout << "max: " << shop.getMaxPrice() << "\n";
return 0;
}
It is not perfect C++ style, but still makes the code easy to read.