Why is my derived class showing as abstract? - c++

Getting an error that says
..\src\CS20 Lab 2 Part 2.cpp:75:38: error: invalid new-expression of abstract class type 'CS_Student'
Base Class:
/*
* Student.h
*
* Created on: Jan 23, 2020
* Author: Student
*/
enter code here
#ifndef STUDENT_H_`#define STUDENT_H_
#include <string>
using namespace std;
class Student {
protected:
string *name;
int *age;
public:
Student();
void setName(string s) ;
void setAge(int i);
string getName() const;
int getAge() const;
virtual void print() = 0;
virtual ~Student();
};
#endif /* STUDENT_H_ */
Student.cpp:
/*
* Student.h
*
* Created on: Jan 23, 2020
* Author: Student
*/
#ifndef STUDENT_H_
#define STUDENT_H_
#include <string>
using namespace std;
class Student {
protected:
string *name;
int *age;
public:
Student();
void setName(string s) ;
void setAge(int i);
string getName() const;
int getAge() const;
virtual void print() = 0;
virtual ~Student();
};
#endif /* STUDENT_H_ */
Derived Class:
/*
* CSStudent.cpp
*
* Created on: Jan 23, 2020
* Author: Student
*/
#include <string>
#include <iostream>
#include "CS_Student.h"
#include "Student.h"
using namespace std;
CS_Student::CS_Student() {
favProgLang = new string;
cout << "CS_Student object created!" << endl;
}
void CS_Student::setFavProgLang(string s){
*favProgLang = s;
}
string CS_Student::getFavProgLang() const{
return *favProgLang;
}
void CS_Student::print() const{
cout << "\nPRINT REPORT FOR CS_STUDENT OBJECT" << endl;
cout << "\tName: " << *name << endl;
cout << "\tAge: " << *age << endl;
cout << "\tFavorite Programming Language: " << *favProgLang << endl;
}
CS_Student::~CS_Student() {
delete favProgLang;
cout << "CS_Student object destroyed!" << endl;
}
/*
void setFavProgLang(string s);
string getFavProgLang() const;
void print() const;
*/
Derived header:
/*
* CSStudent.h
*
* Created on: Jan 23, 2020
* Author: Student
*/
#ifndef CS_STUDENT_H_
#define CS_STUDENT_H_
#include <string>
#include "Student.h"
#include <iostream>
using namespace std;
class CS_Student: public Student {
private:
string *favProgLang;
public:
CS_Student();
void setFavProgLang(string s);
string getFavProgLang() const;
void print() const;
virtual ~CS_Student();
};
#endif /* CS_STUDENT_H_ */
Main:
#include "CS_Student.h"
#include "EnglishStudent.h"
/*******************************************************************************
* Function Prototypes
*******************************************************************************/
#include <iostream>
#include <string>
using namespace std;
void getInput(CS_Student**, const int);
void getInput(EnglishStudent**, const int);
void display(Student*);
/*******************************************************************************
* int main()
* Starting point of the program.
*
* Output:
* An integer to signal to the OS the exit code.
*******************************************************************************/
int main() {
// variables
const int CS_SIZE = 2;
const int ENG_SIZE = 3;
CS_Student* csArray[CS_SIZE];
EnglishStudent* engArray[ENG_SIZE];
// call the getInput method overloads for both arrays
getInput(csArray, CS_SIZE);
getInput(engArray, ENG_SIZE);
// call the polymorphic display function for both arrays
for (int i = 0; i < CS_SIZE; i++) {
display(csArray[i]);
}
for (int i = 0; i < ENG_SIZE; i++) {
display(engArray[i]);
}
// release the dynamic memory for objects inside both arrays
for (int i = 0; i < CS_SIZE; i++) {
delete csArray[i];
}
for (int i = 0; i < ENG_SIZE; i++) {
delete engArray[i];
}
// terminate
return 0;
}
/*******************************************************************************
* void getInput(CS_Student** objArray, const int SIZE)
* Use a for loop to create dynamic CS student objects. Prompt the user for the
* name/age/favorite programming language of each CS student. Store the
* information in the dynamic object.
*
* Inputs:
* objArray - a double-pointer that should be treated as an array of dynamic
* CS student objects
* SIZE - a constant integer that represents the size of the array
*******************************************************************************/
void getInput(CS_Student** objArray, const int SIZE) {
// variables
string name = "", fpl = "";
int age = 0;
// for each CS student
for (int i = 0; i < SIZE; i++) {
// create the dynamic CS student object
objArray[i] = new CS_Student();
// prompt and store the name of the current CS student
cout << "Enter the name for CS student #" << i + 1 << ": ";
getline(cin, name);
// prompt and store for the age of the current CS student
cout << "Enter the age for CS student #" << i + 1 << ": ";
cin >> age;
// need to ignore the newline in the buffer
cin.ignore();
// prompt and store the favorite programming language of the current
// CS student
cout << "Enter the favorite programming language for CS student #"
<< i + 1 << ": ";
getline(cin, fpl);
// add the data to the dynamic object
objArray[i]->setName(name);
objArray[i]->setAge(age);
objArray[i]->setFavProgLang(fpl);
}
}
/*******************************************************************************
* void getInput(EnglishStudent** objArray, const int SIZE)
* Use a for loop to create dynamic English student objects. Prompt the user
* for the name/age/favorite book of each English student. Store the
* information in the dynamic object.
*
* Inputs:
* objArray - a double-pointer that should be treated as an array of dynamic
* English student objects
* SIZE - a constant integer that represents the size of the array
*******************************************************************************/
void getInput(EnglishStudent** objArray, const int SIZE) {
// variables
string name = "", book = "";
int age = 0;
// for each English student
for (int i = 0; i < SIZE; i++) {
// create the dynamic English student object
objArray[i] = new EnglishStudent();
// prompt and store the name of the current English student
cout << "Enter the name for English student #" << i + 1 << ": ";
getline(cin, name);
// prompt and store for the age of the current English student
cout << "Enter the age for English student #" << i + 1 << ": ";
cin >> age;
// need to ignore the newline in the buffer
cin.ignore();
// prompt and store the favorite book of the current English student
cout << "Enter the favorite book for English student #"
<< i + 1 << ": ";
getline(cin, book);
// add the data to the dynamic object
objArray[i]->setName(name);
objArray[i]->setAge(age);
objArray[i]->setFavBook(book);
}
}
/*******************************************************************************
* void display(Student* obj)
* A polymorphic function. Simply calls the (virtual) print method. Used to
* demonstrate polymorphism. Any derived class that inherits from the Student
* class can be used as an argument.
*
* Input:
* obj - a pointer to an object that inherits from the Student class
*******************************************************************************/
void display(Student* obj) {
obj->print();
}
Really confused because Student is my base class which has the pure virtual function
virtual void print() = 0;
and it's overridden in CS_Student
void CS_Student::print() const
I've also tried changing CS_Student here to Student and it doesn't change anything. Thanks in advance

Base: virtual void print() = 0;
Derived: void print() const;
That extra const in the derived version changes the signature of the derived function, the instance variable this is const, so that it doesn't match the base function. Either the base must be const or the derived must not be const. Prefer the former.
Eg.
virtual void print() = 0;
becomes
virtual void print() const= 0;
In C++ and more recent standard revisions you can catch this more easily by marking all functions you expect to override a base class function with the override keyword. This almost always results in a more easily understood error message.
Eg.
void print() const override;
results in (on my tool chain)
error: 'void CS_Student::print() const' marked 'override', but does not override
void print() const override;

Related

In the Test Driver cannot get getName function, getStockNo function , or getNoInStock function to output the correct information

In the Test Driver.cpp file, I cannot get the getName, getStockNo, or getNoInStock to output the correct information. The set functions and the get functions for classifications and price work. I do not know how to get char from the getName function. I have attached both the CPP file and the header file. I am only having issues with the Test Driver.cpp file
//Test Driver.cpp
#include <iostream>
#include <fstream>
#include <string>
#include <cctype>
#include <string>
#include "GameRecord.h"
using namespace std;
int main()
{
// Creating the object of the GameRecord class
GameRecord gr1;
// Setting the values in the GameRecord object gr1 as per the given question
gr1.setName("VideoGame");
gr1.setStockNo(200);
gr1.setClassification(10);
gr1.setPrice(250.0);
gr1.setNoInStock(5);
//problem here
char video;
int size = 0;
gr1.getName(&video, size);
cout << "Getting Name: " << video << endl;
//problem here
long stkNo = 0;
gr1.getStockNo();
cout << "Getting Stock Number: " << stkNo << endl;
int classification;
gr1.getClassification(classification);
cout << "Getting Classification: " << classification << endl;
double price;
gr1.getPrice(price);
cout << "Getting Price: $" << price << endl;
//problem here
int NoInStock = 0;
gr1.getNoInStock();
cout << "Getting Number in Stock: " << NoInStock << endl;
// Creating another object of the GameRecord class
GameRecord gr2("VideoGame2", 100, 5, 150.0);
// To print the Gamerecord object values, call the printRecord() function
gr2.printRecord();
}
//GameRecord.cpp file
#include <iostream>
#include <string.h>
#include "GameRecord.h"
using namespace std;
// Default Constructor used to initialize the data members of the class
GameRecord::GameRecord()
{
strcpy_s(m_sName, "");
m_lStockNo = 0;
m_iClassification = 0;
m_dPrice = 0.0;
m_iCount = 0;
}
// Argumented Constructor is used to initializing the data members of the class with the
respective values GameRecord::GameRecord(const char* name, long sn, int cl, double or)
{
strcpy_s(m_sName, sizeof(m_sName), name);
m_lStockNo = sn;
m_iClassification = cl;
m_dPrice = or ;
m_iCount = 1;
}
// Destructor of the class
GameRecord::~GameRecord()
{
}
/* Getter Setter Method of the GameRecord class, Getter method is used to
get the respective values and setter is used to set the values*/
void GameRecord::getName(char* name, int nameSize)
{
strcpy_s(name, nameSize, m_sName);
}
void GameRecord::setName(const char* name)
{
strcpy_s(m_sName, sizeof(m_sName), name);
}
long GameRecord::getStockNo()
{
return m_lStockNo;
}
void GameRecord::setStockNo(long sn)
{
m_lStockNo = sn;
}
void GameRecord::getClassification(int& cl)
{
cl = m_iClassification;
}
void GameRecord::setClassification(int cl)
{
m_iClassification = cl;
}
void GameRecord::getPrice(double& c)
{
c = m_dPrice;
}
void GameRecord::setPrice(double c)
{
m_dPrice = c;
}
int GameRecord::getNoInStock()
{
return m_iCount;
}
void GameRecord::setNoInStock(int count)
{
m_iCount = count;
}
void GameRecord::printRecord()
{
cout << m_sName << " " << m_lStockNo << " " << m_iClassification << " " << m_dPrice << " "
<< m_iCount << endl;
}
//GameRecord.h file
#pragma once
#include <iostream>
#include <string.h>
using namespace std;
class GameRecord
{
private:
char m_sName[128]; // used to store the name of a videogame or videogame system.
long m_lStockNo; // used to store a unique stock number for the videogame or videogame
system int m_iClassification; // used to code specific information about the videogame or
videogame system
.double m_dPrice; // used to store the price of this videogame or videogame system
int m_iCount; // used to store the number of copies of this item currently in the
inventory.
public
: GameRecord(); // constructor set the member variables to the following initial values.
// set the member variables to the values passed into the function and initialize the
m_iCount variable to one(1).GameRecord(const char* name, long sn, int cl, double price);
~GameRecord(); //The destructor shall be an empty, place - holder function.
// copy the member variable m_sName into the character array pointed to by the function argument.
void getName(char* name, int nameSize);
// function will copy the function argument into the member variable m_sName.
void setName(const char* name);
// function shall return the value stored in the member variable m_lStockNo.
long getStockNo();
// function will copy the function argument into the member variable m_lStockNo.
void setStockNo(long sn);
// function will copy the member variable m_iClassification into the interger variable referenced by the function argument.
void getClassification(int& cl);
// function will copy the function argument into the member variable m_iClassification.
void setClassification(int cl);
// function will copy the member variable m_dPrice into the double variable pointed to by the function argument.
void getPrice(double& c);
// function will copy the function argument into the member variable m_dPrice.
void setPrice(double c);
int getNoInStock(); // function shall return the value stored in the member variable
m_iCount.
void
setNoInStock(int count); // function will copy the function argument into the member
variable m_iCount.
void
printRecord(); // shall print to the screen all data found in the record
};
the function getName should be used as
int size=...;
char*name=new char[size];
c.gerName(name,size);
because it works by copying the name to the pointer got in the input

how do i initialize 2 static members belonging to 2 different derived classes

New to c++. I'm solving questions to understand better.
So, i have to make a program which has a parent class called Person and it has 2 derived classes named Student and Professor. The parent class Person has normal variables - std::string name and int age. The derived class Student has variables int sum, int marks[6] and static int cur_id. The derived class Professor has variables int publications and static int cur_id.
Now both the derived classes have 2 overloaded methods, getdata() - gets input from user and putdata() - prints data.
Also both have a static variable named cur_id which gets incremented when an object gets constructed.
Now the problem comes when i try to initialize the static variables using the below code -
int Student::cur_id;
int Professor::cur_id;
I get the following error -
'int Professor::cur_id': redeclaration of member is not allowed.
here is the full code -
#include <cmath>
#include <cstdio>
#include <vector>
#include <iostream>
#include <algorithm>
#include <string>
using namespace std;
class Person
{
protected:
std::string name;
int age;
public:
Person()
:age(0)
{}
};
class Professor : public Person
{
private:
int publications;
static int cur_id;
public:
Professor() //constructor
:Person(), publications()
{
++cur_id;
}
void getdata()
{
std::cin >> name >> age >> publications;
}
void putdata()
{
std::cout << name << " " << age << " " << publications << " " << cur_id << std::endl;
}
};
class Student : public Person
{
private:
int marks[6];
static int cur_id;
int sum;
public:
Student() //constructor
:marks{ 0 }, sum(0), Person()
{
++cur_id;
}
void getdata()
{
std::cin >> name >> age;
for (int index{}; index < 6; ++index)
{
std::cin >> marks[index];
sum += marks[index];
}
}
void putdata()
{
std::cout << name << " " << age << " " << sum << " " << cur_id;
}
};
int Student::cur_id;
int Professor::cur_id;
int main()
{
Student student;
student.getdata();
student.putdata();
Student nobita;
nobita.getdata();
nobita.putdata();
return 0;
}
Any help is appreciated, thanks
You should define cur_id in Professor class as static.

How Do I Deal With This C++ Multimap Issue?

I am a beginner in C++ working on simple program and I ran into an issue which left me stumped... Basically I created a multimap that accepts a part of string person name and a pointer to a person object.
So My first function to work with was the "Add()" function. I basically construct a new person with a name and age and then set a pointer to that object. Then I insert the name and the object into the multimap as a pair.
The problem happens when I run the find() function... My output only gives me a valid name but for the age I get what seems like a truncated memory address or a random number? Since i'm a beginner I am pretty sure I am doing something very simple yet very stupid. I don't think you will need to run the code since it's so simple. All help is appreciated. Thank you!
My runnable file:
#include "Person.h"
#include <map>
using namespace std;
multimap<string, Person*> personMap;
multimap<string, Person*>::iterator counter;
void add()
{
string name;
int age;
cout << "Please enter the name of the person: ", cin >> name;
cout << "Please enter the age of the person: ", cin >> age;
Person generatedPerson(name, age);
// Avoid dynamic class pointers for memory optimization.
// Avoided: Person* pointer = new Person(name, age).
Person *pointer = &generatedPerson;
personMap.insert({name, pointer});
}
void find()
{
string personToBeFound;
cout << "Who do you wish to find, friend: ", cin >> personToBeFound;
for (counter = personMap.begin(); counter != personMap.end(); counter++)
{
if (counter->first == personToBeFound)
{
cout << "\nName: " << counter->first << " Age: " << counter->second->getAge() << endl;
}
else if (counter->first != personToBeFound)
{
cout << "Error 404, person does not exist..." << endl;
}
}
}
// Experimental....
int main(int argc, char* argv[])
{
int menuChoice = -1;
while (menuChoice != 0)
{
cout << "\nPlease enter: "
"\n1 - to add a person "
"\n2 - to find a person"
"\n0 - to quit\n" << endl;
cin >> menuChoice;
switch(menuChoice)
{
case 1: add();
break;
case 2: find();
break;
case 0: menuChoice = 0;
}
}
}
HEADER FILE:
#ifndef PERSON_H
#define PERSON_H
#include <string>
#include <vector>
#include <iostream>
class Person {
public:
// Constructors
/**
* Create a Person with the given name and age.
*
* #param name name of the person
* #param age age of the person - defaults to 0
*/
Person(const std::string& name, unsigned short age = 0);
// No explicit destructor necessary
// Mutators
/**
* Set the name attribute
*
* #param name name of the person
*/
void setName(const std::string& name);
/**
* Set the age attribute
*
* #param age age of the person
*/
void setAge(unsigned short age);
/**
* Increment the age attribute
*/
void growOlder();
/**
* Add a person to our list of children
*
* #param child Person to add as a child
*/
void addChild(const Person& child);
// Accessors
/**
* #return the Person's name
*/
const std::string& getName() const;
/**
* #return the Person's age
*/
unsigned short getAge() const;
/**
* #return a list of this Person's children
*/
const std::vector<const Person *>& getChildren() const;
/**
* Define the ostream's << operator as a friend of this class
* to allow this object to be printed to an output stream
*
* #param output the stream to print to
* #param p the Person to print
*
* #return the output stream printed to
*/
friend std::ostream& operator<< (std::ostream& output, const Person& p);
private:
// 0-arg Constructor
Person();
// Private attributes
std::string _name;
unsigned short _age;
std::vector<const Person *> _children;
}; // Person
#endif
METHOD DEFINITIONS:
#include "Person.h"
Person::Person(const std::string& name, unsigned short age) :
_name(name) , _age(age) {
}
void Person::setName(const std::string& name) {
_name = name;
}
void Person::setAge(unsigned short age) {
_age = age;
}
void Person::growOlder() {
_age++;
}
void Person::addChild(const Person& child) {
_children.push_back(&child);
}
const std::string& Person::getName() const {
return _name;
}
unsigned short Person::getAge() const {
return _age;
}
const std::vector<const Person *>& Person::getChildren() const {
return _children;
}
std::ostream& operator<< (std::ostream& output, const Person& aPerson) {
// Print our attributes to the output stream
return output << "Name: '" << aPerson._name << "', Age: " << aPerson._age;
}
Hi the comment of #1201ProgramAlarm is absolutely right, however, I thought by myself, how would I go about "rescuing" the program (a) with minimal effort, (b) to get a correct version and (c) very much in terms of the original version.
So here's a new main.cc version (Person.h, Person.cc needn't be changed):
#include "Person.h"
#include <map>
using namespace std;
multimap <string, Person *> personMap;
multimap <string, Person *>::iterator counter;
void add()
{
string name;
int age;
cout << "Please enter the name of the person: ", cin >> name;
cout << "Please enter the age of the person: ", cin >> age;
personMap.insert({ name, new Person(name, age) });
}
void find()
{
string personToBeFound;
cout << "Who do you wish to find, friend: ", cin >> personToBeFound;
for (counter = personMap.begin(); counter != personMap.end(); counter++)
{
if (counter->first == personToBeFound)
{
cout << "\nName: " << counter->first
<< " Age: " << counter->second->getAge() << endl;
}
else
{
cout << "Error 404, person does not exist..." << endl;
}
}
}
int main(int argc, char* argv[])
{
int menuChoice = -1;
while (menuChoice != 0)
{
cout << "\nPlease enter: "
"\n1 - to add a person "
"\n2 - to find a person"
"\n0 - to quit\n" << endl;
cin >> menuChoice;
switch(menuChoice)
{
case 1:
add();
break;
case 2:
find();
break;
case 0:
menuChoice = 0;
break;
}
}
// -- How to go about clearing the heap? --
for (counter = personMap.begin(); counter != personMap.end(); counter++)
{
if (counter->second) {
delete counter->second;
counter->second = nullptr;
}
}
}
I compiled using g++ -o main Person.cc main.cc. Regards, M.
Update after this question:
Why shouldn't I just delete the keys instead of just the values of the multimap <string, Person *> entries?
Answer:
I just wanted to show what could be done to prevent orphaned Person objects on the heap when the multimap went out of (local) scope and would thus be destroyed automatically by the C++ system. More specifically:
(a) As in C, what is malloc-ed needs to be free-ed again later, the equivalent is true in C++: what is new-ed needs to be delete-ed later. This is best practice to prevent memory leaks in the long run.
(b) Now, back to our multimap <string, Person *>. Here, the keys are strings and the values are pointers to Person objects. These Person pointers are the only way left to get a hold on the corresponding Person objects allocated on the heap in calls to the add() function.
(c) In our case, the whole program is going to stop anyway after the multimap gets destroyed automatically, so delete-ing the Person objects using that extra for-loop isn't as important here, because Person objects remaining on the heap are garbage-collected by the operating system after the corresponding process has terminated, anyway.

Cannot locate segmentation fault. Allocating memory in constructor?

I've been at this for hours, but I can't seem to locate where the core dump is coming from. I've limited it down to the main constructor and a couple functions but I cant find where the error is coming from. Any help would be appreciated.
destructor
Vehicle:: ~Vehicle(){
delete [] name;
}
base header
#ifndef VEHICLE_H
#define VEHICLE_H
#include <iostream>
#include <string>
using namespace std;
class Vehicle{
protected:
char *name;
static ostream *out ;
public:
Vehicle();
Vehicle(string &n);
Vehicle (const Vehicle & b);
~Vehicle();
Vehicle& operator =(const Vehicle &b);
virtual void print(void) = 0;
virtual void read(void) = 0;
};
#endif // VEHICLE_H
Constructor in base implementation
Vehicle :: Vehicle(){
name = new char[1];
strcpy(name[0], "");
}
Vehicle :: Vehicle(string &n){
int len = n.length()+ 1;
name = new char[len];
strcpy(name,n.c_str());
}
Vehicle :: Vehicle(const Vehicle & v){
int len = strlen(v.name)+ 1;
name = new char[len];
strcpy(name,v.name);
}
Header for inherited class
#ifndef MOTORVEHICLE_H
#define MOTORVEHICLE_H
#include <cstring>
#include "vehicle.h"
class MotorVehicle: public Vehicle{
protected:
string make;
string model;
double mpg;
public:
MotorVehicle();
MotorVehicle (const string &n,const string &m = "",const string &md = "", const double &mp = 0.0);
//accessor functions
string getName()const;
string getMake()const;
string getModel()const;
double getMpg()const;
ostream & getOut();
//mutator functions
string setName();
void setMake();
void setModel();
void setMpg();
void setOut(ostream & o);
//virtual functions
void print();
void read();
};
#endif // MOTORVEHICLE_H
Inherited class.
#include "motorVehicle.h"
#include <string>
#include <iostream>
MotorVehicle:: MotorVehicle(): Vehicle(), make(""), model(""), mpg(0.0){
make = "";
model = "";
mpg = 0.0;
}
MotorVehicle :: MotorVehicle(const string &n, const string &m, const string &md, const double &mp){
int len = n.length()+ 1;
delete [] name;
name = new char[len];
strcpy(name,n.c_str());
make = m;
model = md;
mpg = mp;
}
//accessor functions
string MotorVehicle :: getName()const{
string temp(name);
return temp;
}
string MotorVehicle :: getMake()const {
return make;
}
string MotorVehicle :: getModel()const {
return model;
}
double MotorVehicle :: getMpg()const {
return mpg;
}
ostream & MotorVehicle :: getOut(){
return *out;
}
//mutator functions
string MotorVehicle :: setName(){
cerr << "dododd" <<endl;
string nm1;
cin >> nm1;
int len = nm1.length()+ 1;
delete [] name;
name = new char[len];
strcpy(name,nm1.c_str());
}
void MotorVehicle :: setMake(){
cin >> make;
}
void MotorVehicle :: setModel(){
cin >> model;
}
void MotorVehicle :: setMpg(){
cin >> mpg;
}
void MotorVehicle :: setOut(ostream & o){
out = &o;
}
//virtual function
void MotorVehicle :: print(){
*out << name << make << model << mpg <<" ";
}
void MotorVehicle :: read(){
*out << "Please enter name for this Vehicle: " << endl;
setName();
*out << "Please enter make for this Vehicle: " << endl;
setMake();
*out << "Please enter model for this Vehicle: " << endl;
setModel();
*out << "Please enter miles per gallon for this Vehicle: " << endl;
setMpg();
}
Main
#include <iostream>
#include <fstream>
#include <string>
#include <vector>
#include <typeinfo>
#include "motorVehicle.h"
// car.h & truck.h included twice to test #ifndef #define ... #endif structure
#include "car.h"
#include "car.h"
#include "truck.h"
#include "truck.h"
typedef vector<MotorVehicle *> vectorOfMotorVehicle;
using namespace std;
// prompt the user for the Vehicle type to create, and get the reply
string prompt(void);
int main() {
vectorOfMotorVehicle v; // store dynamically created MotorVehicles
// or objects derived from MotorVehicles
int numVehicles = 0; // denotes how many MotorVehicles we have
string reply; // indicates type of MotorVehicle to build
bool error = false; // set when a user response is in error
string outputLocation; // where the output of print() will go
ofstream *out = NULL;
MotorVehicle *m;
// uncomment following line to test that Vehicle is an abstract base class
// Vehicle theVehicle;
// push a Vehicle into the vector so first "real" Vehicle is at position 1
m = new MotorVehicle("None");
v.push_back(m);
// chose where the output will go
cout << "Where would you like the output? ";
cin >> outputLocation;
if (outputLocation == "stdout") {
; // no action to take, because stdout (i.e., cout) is the default
} else if (outputLocation == "stderr") {
v[0]->setOut(cerr);
} else {
out = new ofstream;
out->open(outputLocation.c_str());
if (out->fail()) {
cerr << "Error: error writing to " << outputLocation << endl;
return 1;
}
v[0]->setOut(*out);
}
// get the type of Vehicle to create
reply = prompt();
// loop, reading vehicle descriptions, until a "quit" command is received
while (reply != "quit") {
// create the new MotorVehicle object and push it into the vector
switch (toupper(reply[0])) {
case 'T' : m = (MotorVehicle *) (new Truck);
v.push_back(m);
break;
case 'C' : m = (MotorVehicle *) (new Car);
v.push_back(m);
break;
case 'Q' : reply = "quit";
continue;
default : cerr << "Incorrect response\n\n";
error = true;
}
// if no error, then we have a new Vehicle to initialize via read()
if (!error) {
numVehicles++;
v[numVehicles]->read();
}
// reset error flag, and request a new Vehicle type
error = false;
reply = prompt();
}
// report on what Vehicles were created to test read() and print()
for (int i = 0; i <= numVehicles; i++) {
//*out << "Vehicle " << i << endl;
// print the Vehicle characteristics (attributes)
v[i]->print();
//*out << endl;
// free the storage for this Vehicle
delete v[i];
}
// if we opened an output file, then close it
if (out != NULL) {
out->close();
delete out;
}
return 0;
}
// prompt the user for the Vehicle type to create, and get the reply
string prompt() {
string reply; // the user reponse to the prompt
// prompt for and get user response
cout << "\nWhich type of vehicle would you like to initialize"
<< "\n--car or truck (or \"quit\" to exit): ";
cin >> reply;
return reply;
}
I tried to narrow it down as much as possible, but the other two inherited classes follow a similar inheritance so I omitted it. Any help would be hugely appreciated. Thanks again

c++ Class -> Vector -> File

I have this requirement.
I am trying to make a simple database schema, a little different than what I have seen in here. I have a class file (client.h) with it's implementation (client.cpp):
#ifndef CLIENT_H_
#define CLIENT_H_
#include <iostream>
using namespace std;
class Client {
public:
// constructors
Client();
Client(string new_name, string new_tel, string new_addr);
// getters
string getName();
string getAddr();
string getTel();
// setters
void setName(string);
void setAddr(string);
void setTel(string);
void display();
void input();
private:
// fields
string name;
string addr;
string tel;
};
#endif /* CLIENT_H_ */
/*
*ad client.cpp
*
* Created on: Jan 12, 2017
* Author: niksarid
*/
#include <iostream>
#include "client.h"
using namespace std;
Client::Client() {
setName("");
setAddr("");
setTel("");
}
Client::Client(std::string new_name, std::string new_addr, std::string new_tel) {
setName(new_name);
setAddr(new_addr);
setTel(new_tel);
}
string Client::getName() {
return name;
}
string Client::getAddr() {
return addr;
}
string Client::getTel() {
return tel;
}
void Client::setName(string p_name) {
name = p_name;
}
void Client::setAddr(string p_addr) {
addr = p_addr;
}
void Client::setTel(string p_tel) {
tel = p_tel;
}
void Client::input() {
string tmp;
cout << "INPUT CLIENT INFO" << endl;
cout << "Name: ";
cin >> tmp;
setName(tmp);
cout << "Address: ";
cin >> tmp;
setAddr(tmp);
cout << "Telephone: ";
cin >> tmp;
setTel(tmp);
}
void Client::display() {
cout << name << "\t" << addr << "\t" << tel << endl;
}
So I am trying to make a Company class that will hold a vector of Clients and at the startup of the program it will load the datafile "clients.dat", into the vector. I will be able to add a client or delete a client from the vector. At the end the vector will be saved back to "clients.dat".
So, the (company.h) file is like this:
class Company {
public:
Company();
~Company();
void add_client();
void print_clients();
void loadClientsFromFile();
void saveClientsToFile();
private:
vector<Client> clients;
} cmp;
#endif /* COMPANY_H_ */
but I can't seem to reference clients vector in any of the public methods of the class company.
EDIT: Sorry! Forgot the important part!!
For example when I try to add_client(),
void add_client() {
Client c;
c.input();
clients.push_back(c);
}
but I get
../src/company.cpp:49:2: error: 'clients' was not declared in this scope
clients.push_back(c);
So, how to achieve that?
As Morgan mentioned in the comments, this problem typically arises when you try to define the member function in your implementation file, but forget to add the class name as prefix (e.g. void add_client() {} instead of void Company::add_client() {}.
This mistake is common and can easily go unnoticed, since it is perfectly legal to define a new free function called add_client in your file, that would have nothing to do with the Company class. That's why the compiler only complains when you try to access a data member, but not before.