exception unhandled violation access - c++

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?

Related

Passing array of pointers to object c++

I have to create an array of pointer to class objects.
Then I have with function AddStudent I have to change/create a new student (add his data to pointer address).
In last step function ShowAllStudents has to show all students. But I shows only the last added student.
Every new object is beeing created in array index of 0. I don't know why.
There is my code:
index.html:
#include <iostream>
#include "student.h"
void AddStudent(Student* pointer_array[], int n)
{
int IndexNr{}, id{};
std::string name{}, surname{};
std::cout << "Write IndexNr:";
std::cin >> IndexNr;
for(int i = 0; i < n; i++){
if (IndexNr != pointer_array[i]->Student::IndexNr && pointer_array[i]->Student::name == "none")
{
i = id;
pointer_array[i]->Student::IndexNr = IndexNr;
break;
}
else if (IndexNr == pointer_array[i]->Student::IndexNr) {
i = id;
break;
}
}
std::cout << "Student's name: ";
std::cin >> name;
pointer_array[id]->Student::name = name;
std::cout << "Student's surname ";
std::cin >> surname;
pointer_array[id]->Student::surname = surname;
}
void ShowAllStudents(Student* pointer_array[], int n)
{
for (int i = 0; i < n; i++) {
if (pointer_array[i]->Student::name != "none")
{
std::cout << "<id>: " << pointer_array[i]->Student::IndexNr << " <Name>: " << pointer_array[i]->Student::name << " <Surname>: " << pointer_array[i]->Student::surname << std::endl;
}
else if (pointer_array[i]->Student::name != "none" && i == (n - 1))
std::cout << "<id>: no data" << std::endl;
}
}
int main()
{
int n{10};
Student* pointer_array[10];
for (int i = 0; i < n; i++)
pointer_array[i] = new Student;
AddStudent(pointer_array, n);
AddStudent(pointer_array, n);
AddStudent(pointer_array, n);
ShowAllStudents(pointer_array, n);
return 0;
}
student.h
#include <iostream>
#ifndef STUDENT_H_
#define STUDENT_H_
class Student {
public:
int IndexNr;
std::string name;
std::string surname;
Student() {
IndexNr = 0;
name = "none";
surname = "none";
}
};
#endif
It shows only the last edited student.

Reading values from File into a class variable?

I'm trying to write a code that will get values from a file and store them into a class variable. I'm not saving them according to my code. I would really appreciate the help. I don't know where my error is. The first value from the file is the number of class objects there is in total.
class customer {
private:
string *names;
char *plans;
int *hours;
int customerTotal;
public:
string name;
char plan;
int hour;
customer() {
name = "";
plan = ' ';
hour = 0;
customerTotal = 0;
}
void setName(string x) {
names[customerTotal] = x;
}
void setPlan(char x) {
plans[customerTotal] = x;
}
void setHours(int x){
hours[customerTotal] = x;
customerTotal++;
}
void printArray(){
for (int i = 0; i < customerTotal;i++){
cout << names[i] << plans[i] << hours[i] << endl;
}
}
};
int main() {
int numCustomers;
ifstream inFile;
string n;
char p;
int h;
inFile.open("customers.txt");
if (!inFile)
{
cout << "File not found!" << endl << endl;
system("pause");
return 1;
}
customer x;
inFile >> numCustomers;
while (!(inFile.eof())) {
inFile >> n >> p >> h;
x.setName(n);
x.setPlan(p);
x.setHours(h);
}
x.printArray();
inFile.close();
}

C++ Console is blank when program is run

This might be a stupid question I'm still very new to coding. For my CS class I was given code for the basics of a boardgame. When I try to run the code it just comes up blank in my console, I tried to print "check" at the very beginning of main but still nothing prints to the console. No errors come up
#include <iostream>
#include <string>
#include <fstream>
#include <ctime>
#include <cstdlib>
using namespace std;
class square {
private:
int move;
string message;
char symbol;
public:
square();
void print();
int action();
void set(int, char, string);
};
void print_board(square[], int, int);
void read_board(square[]);
void check_position(int &);
const int board_length = 20;
int main() {
cout << "check";
int current_player = 1, roll;
int player1_position = 0, player2_position = 0;
square the_board[board_length];
srand(time(NULL));
read_board(the_board);
print_board(the_board, player1_position, 1);
print_board(the_board, player2_position, 2);
do {
cout << "\n\n\nPlayer " << current_player << " type enter to roll.\n";
cin.ignore();
roll = 1 + (rand() % 5);
cout << "Player " << current_player << " rolled a " << roll << ".\n";
if (current_player == 1) {
player1_position += roll;
check_position(player1_position);
player1_position += the_board[player1_position].action();
check_position(player1_position);
} else {
player2_position += roll;
check_position(player2_position);
player2_position += the_board[player2_position].action();
check_position(player2_position);
}
print_board(the_board, player1_position, 1);
print_board(the_board, player2_position, 2);
current_player = (current_player % 2) + 1;
} while ((player1_position < board_length-1) && (player2_position < board_length - 1));
current_player = (current_player % 2) + 1;
cout << "\nPlayer " << current_player << " Wins!!!\n";
cin.ignore();
return 0;
}
void read_board(square b[]) {
ifstream infile;
infile.open("game.txt");
int square_number, square_move;
string square_message;
char square_symbol;
while (!infile.eof()) {
infile >> square_number >> square_move >> square_symbol;
getline(infile, square_message);
if (square_number < board_length) {
b[square_number].set(square_move, square_symbol, square_message);
}
}
}
void print_board(square b[], int player_position, int player_number) {
for (int i=0; i < board_length; i++) {
if (i != player_position) {
b[i].print();
} else {
cout << player_number;
}
}
cout << "Goal\n";
for (int i=0; i < board_length; i++) {
cout << "-";
}
cout << "\n";
}
void check_position(int &p) {
if (p < 0) {
p = 0;
}
if (p >= board_length) {
p = board_length - 1;
}
}
square::square() {
symbol = ' ';
move = 0;
message = "";
}
int square::action() {
cout << message << endl;
return move;
}
void square::print() {
cout << symbol;
}
void square::set (int m, char s, string a_message) {
move = m;
symbol = s;
message = a_message;
}
Modify you read_board() to
void read_board(square b[]) {
ifstream infile;
infile.open("game.txt");
int square_number, square_move;
string square_message;
char square_symbol;
while (infile >> square_number >> square_move >> square_symbol) {
getline(infile, square_message);
if (square_number < board_length) {
b[square_number].set(square_move, square_symbol, quare_message);
}
}
}
Change cout<<"check"; to cout<<"check"<<endl;
Without the new line added, the out buffer is not flushed before your code gets hung in your read_board function

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);

ambiguous error: template 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.