I am trying to make a program which creates an array of pointers to objects, including inherited objects.
The error I'm getting is on the first bracket ( of the cSClass eg SArray[2] = new cSClass(...); (Last line at the bottom of all the code). The error says "no instance of constructor cSClass::cSClass matches the argument list"
Thank you
All the code is below:
The code for the header of the superclass is:
class sClass;
class sClass {
protected:
std::string name;
int yearBuilt;
public:
// Constructor
sClass(string n = "s1", int yb = 2000) {
name = n;
yearBuilt = yb;
}
// Mutator functions
void setName(string);
void setYearBuilt(int);
// Accessor functions
string getName() {
return name;
}
int getYearBuilt() {
return yearBuilt;
}
// Functions
void getInfo();
};
main class of the superclass:
#include "sClass.h"
using namespace std;
// Mutators
void sClass::setName(string n) {
name = n;
}
void sClass::setYearBuilt(int yb) {
yearBuilt = yb;
}
// Print function
void sClass::getInfo() {
cout << "Name: " << name << endl;
cout << "Year Built: " << yearBuilt << endl;
}
Code for the subclass header:
#include "sClass.h"
class cSClass : public sClass {
protected:
int maxPassengers;
public:
// Constructor
cSClass(int mp = 2000) : sClass() {
maxPassengers = mp;
}
// Mutator functions
void setMaxPassengers(int);
// Accessor functions
int getMaxPassengers() {
return maxPassengers;
}
// Functions
void getInfo() {
}
};
Code for the subclass class:
#include "cSClass.h"
// Mutators
void cSClass::setMaxPassengers(int mp) {
maxPassengers = mp;
}
// Print function
void cSClass::getInfo() {
cout << "Name: " << name << endl;
cout << "Maximum Passengers: " << maxPassengers << endl;
}
And lastly this is the main program code in which i am getting errors where i am trying to fill the array:
#include "sClass.h"
#include "cSClass.h"
int main() {
sClass *SArray[6];
SArray[0] = new sClass(...);
SArray[1] = new sClass(...);
SArray[2] = new cSClass(...);
SArray[3] = new cSClass(...);
}
Edit: Error is at the top, and the arguments I'm passing are
SArray[2] = new cSClass("RMS Queen Mary 2", 2003, 2700);
The constructor needed for this to work is missing:
SArray[2] = new cSClass("RMS Queen Mary 2", 2003, 2700);
It could look like this
class cSClass : public sClass {
cSClass(const std::string& name, int yb, int mp) :
sClass(name, yb),
maxPassengers{mp}
{}
//...
}
You also have some other problems:
You have a non-virtual destructor in the base class. When you delete your objects through a non-virtual base class pointer, only the base class destructor will be called. To fix that, add this to sClass:
virtual ~sClass() = default;
Two definitions of cSClass::getInfo(). Settle for only declaring the function in the class definition and leave the definition of the member function in the .cpp file as-is.
Memory leaks since you don't delete what you've newed. To avoid that problem, it's better to use smart pointers that will delete the object when it goes out of scope, like it will in case an exception is thrown (that you catch). Example:
#include <memory>
//...
std::unique_ptr<sClass> SArray[6]; // or std::array<std::unique_ptr<sClass>, 6> sArray;
SArray[2] = std::make_unique<sClass>();
SArray[2] = std::make_unique<cSClass>("RMS Queen Mary 2", 2003, 2700);
Note: If you instead want a dynamic amount of sClass pointers, use a std::vector:
#include <vector>
//...
std::vector<std::unique_ptr<sClass>> SArray;
SArray.push_back(std::make_unique<sClass>());
SArray.push_back(std::make_unique<sClass>());
SArray.push_back(std::make_unique<cSClass>("RMS Queen Mary 2", 2003, 2700));
SArray.push_back(std::make_unique<cSClass>("RMS Queen Mary 2", 2003, 2700));
There are two fundamental errors in your code!
First, you have provided two definitions for the getInfo member function of the cSClass. If you want to keep the second (out-of-body) definition, then you need to remove the definition part of the (in-body) declaration. So, replace:
// Functions
void getInfo() { /// Note: adding the { } provides a function DEFINITION
}
with this:
// Functions
void getInfo(); // No body provided, so it's JUST a declaration (defined elsewhere)
Then, the calls you make to your constructors cannot have the ... in the argument list (though I'm not sure what you are trying to achieve with this). Simply provide empty argument lists:
SArray[0] = new sClass();
SArray[1] = new sClass();
SArray[2] = new cSClass();
SArray[3] = new cSClass();
or, as there is no argument, you can invoke the 'default' constructor by omitting the argument lists completely:
SArray[0] = new sClass;
SArray[1] = new sClass;
SArray[2] = new cSClass;
SArray[3] = new cSClass;
Also, for completeness, remember to free the memory for the objects you created with new, when you're done with them:
delete SArray[0];
delete SArray[1];
delete SArray[2];
delete SArray[3];
Feel free to ask for further clarification and/or explanation.
Related
How to fix the function 'func' so that it returns the objects without being destroyed?
function 'func' must add the objects to a list and return them but be destroyed
The Smoothy abstract class has a purely virtual description method (). DecoratorSmoothy
contains a smoothy, description () and getPret () methods return the description and price
aggregate smoothy.
SmoothyCuFream and SmoothyCuUmbreluta classes add the text “cu crema”
respectively “cu umbreluta” in the description of the smoothy contained. The price of a smoothy that has the cream increases by 2 euro, the one with the umbrella costs an extra 3 euro.
BasicSmoothy class is a smoothy without cream and without umbrella, method
description () returns the name of the smothy
#include <iostream>
#include <vector>
using namespace std;
class Smoothy {
private:
int pret=0;
public:
virtual string descriere() = 0;
int getPret(){
return pret;
}
void setPret(int a) {
pret += a;
}
};
class BasicSmooty : public Smoothy {
private:
string nume;
public:
BasicSmooty(string n) :
nume { n } {}
string descriere() {
return nume;
}
};
class DecoratorSmoothy : public Smoothy {
private:
Smoothy* smooty;
public:
DecoratorSmoothy() = default;
DecoratorSmoothy(Smoothy* n) :
smooty{ n } {}
string descriere() {
return smooty->descriere();
}
int getPret() {
return smooty->getPret();
}
};
class SmootyCuFrisca : public DecoratorSmoothy {
private:
BasicSmooty bsc;
public:
SmootyCuFrisca(string desc) :
bsc{ desc } {}
string descriere() {
setPret(2);
return bsc.descriere() + " cu frisca ";
}
};
class SmootyCuUmbreluta : public DecoratorSmoothy{
private:
BasicSmooty bsc;
public:
SmootyCuUmbreluta(string desc) :
bsc{ desc } {}
string descriere() {
setPret(3);
return bsc.descriere() + " cu umbreluta ";
}
~SmootyCuUmbreluta() {
cout << "rip";
}
};
vector<Smoothy*> func(void)
{
std::vector<Smoothy*> l;
SmootyCuFrisca a1{ "smooty de kivi" };
SmootyCuUmbreluta a2{ "smooty de kivi" };
SmootyCuFrisca a3{ "smooty de capsuni" };
BasicSmooty a4{ "smooty simplu de kivi" };
l.push_back(&a1);
l.push_back(&a2);
l.push_back(&a3);
l.push_back(&a4);
return l;
}
int main() {
vector<Smoothy*> list;
// Here when i call func() objects are distroyed
list = func();
return 0;
}
In func you are storing the address of function local variables in l. So when you return l from the function, all the Smoothy* are now pointing to invalid memory.
To fix this, you can allocate memory for each pointer you add to l, like this:
l.push_back(new Smoothy{a1}); // instead of l.push_back(&a1);
// etc. for a2, a3, ...
To really get away from this problem, consider not using pointers at all. If your design doesn't need it, you can get rid of the pointers, and you'll save yourself a lot of trouble.
Well, when a method returns, of course all local/automatic variables are destroyed. Under the late revision c++ changes, there is the return && modifier, which invokes move semantics, which means for not const local/automatic objects you return, it steals: clones the returned object, making a new object and copying all the primitives and object pointers, then sets the object pointers to null so they cannot be deleted/freed by the destructor. (Note that C free of a null pointer does nothing!) For const, of course, it must deep copy.
There's still a whole load of stuff I do not understand about objects and classes in c++, nothing I have read so far has helped me understand any of it and I'm slowly piecing information together from exercises I manage to complete.
Few main points:
When an object is created from a class, how can you access the name of the object in a function in another class? What type of variable is the name of the object stored in? is it even stored anywhere after it's creation?
My manual has an example of creating an association between two classes;
Aggregationclass
{
public:
...
private:
Partclass* partobject_;
...
};
What does this actually mean? Aggregationclass can access the object partobject in partclass? what variables can be read by aggregationclass from the partclass?
Here is a exercise I'm stuck on from my c++ OOP introductionary class, that expects me to utilize association between classes. (7(2/2)/11)
It consists of uneditable Car class;
#include <iostream>
#include <string>
using namespace std;
class Car
{
public:
void Move(int km);
void PrintDrivenKm();
Car(string make, int driven_km);
private:
string make_;
int driven_km_;
};
Car::Car(string make, int driven_km) : make_(make), driven_km_(driven_km)
{
}
void Car::Move(int km)
{
driven_km_ = driven_km_ + km;
cout << "Wroom..." << km << " kilometers driven." << endl;
}
void Car::PrintDrivenKm()
{
cout << make_ << " car has been driven for" << driven_km_ << " km" << endl;
}
What I have made so far(Person class); I have written most of my questions in comments of this section.
class Person //how do I associate Person class with Car class in a way that makes sense?
{
public:
void ChangeCar(string);
Person(string, string);
int DriveCar(int);
private:
Car* make_;
Car* driven_km_;
string name_;
};
Person::Person(string name, string make) //How do I ensure string make == object created from class Car with same name?
{
Person::name_ = name;
Car::make_ = make_;
}
int Person::DriveCar(int x) //Is this the correct way to use a function from another class?
{
Car::Move(x);
}
void Person::ChangeCar(string y) //this function is wrong, how do I create a function that calls for object from another class with the parameter presented in the call for this function (eg. class1 object(ferrari) = class1 object holds the values of object ferrari from class2?)?
{
Car::make_ = y;
}
and an uneditable main();
int main()
{
Car* dx = new Car("Toyota corolla DX", 25000);
Car* ferrari = new Car("Ferrari f50", 1500);
Person* driver = new Person("James", dx);
dx->PrintDrivenKm();
driver->DriveCar(1000);
dx->PrintDrivenKm();
ferrari->PrintDrivenKm();
driver->ChangeCar(ferrari);
driver->DriveCar(20000);
ferrari->PrintDrivenKm();
return 0;
}
disclaimer: the exercise has been translated from another language, in case of spotting a translation error I failed to notice, please do give notice and I will do my best to fix.
Finished exercise; thank you, u/doctorlove for taking the time with your replies, I can with confidence say that I learned a lot!
class Person
{
public:
void ChangeCar(Car * y);
Person(String name, Car * Car);
int DriveCar(int);
private:
Car * Car_;
int x;
string name_;
string y;
};
Person::Person(string name, Car * Car) : name_(name), Car_(Car)
{
Person::name_ = name;
}
int Person::DriveCar(int x)
{
Car_->Move(x);
}
void Person::ChangeCar(Car * y)
{
Car_ = y;
}
Before talking about pointers, look at the Car class:
class Car
{
public:
void Move(int km);
void PrintDrivenKm();
Car(string make, int driven_km);
private:
string make_;
int driven_km_;
};
You can't get to the private stuff from outside. Period.
You can make (or construct) one
Car car("Zoom", 42);
Since we can see what the constructor does
Car::Car(string make, int driven_km) : make_(make), driven_km_(driven_km)
{
}
it's clear it saves away the string and int in the private member variables make_ and driven_km_.
Now we can call the public functions on this instance:
car.PrintDrivenKm();
car.Move(101);
car.PrintDrivenKm();
So, we've made a car and called some functions.
We could make a car pointer and call its functions too. We need to delete stuff otherwise we leak.
Car * car = new Car("Zoom", 42);
car->PrintDrivenKm();
car->Move(101);
car->PrintDrivenKm();
delete car;
Now to your problems.
You have a started writing a Person class which has two (private) cars (pointers) make_ and driven_km_. The constructor Person(string, string); takes two strings, but main doesn't send it two strings:
Car* dx = new Car("Toyota corolla DX", 25000);
// ...
Person* driver = new Person("James", dx);
It will be sent a string and a Car *; something like this
Person(string name, Car *car);
So perhaps it only needs one car (pointer), Car *car_?
Now as for calling your car pointer, Car has Move method; an instance method not a static method, so call it on an instance:
int Person::DriveCar(int x)
{
//Car::Move(x); //no - which car do we move, not a static on ALL cars
car_->Move(x);
}
Now, if the person wants to change car, you made person take a string:
void Person::ChangeCar(string y)
{
//what goes here?
// you want a Car * from a string...
// we did that before
delete car_; //not exception safe, but ...
car_ = new Car(y);
}
Look back at mian:
driver->ChangeCar(ferrari);
so the calling code will try to send a car (pointer) to swap to. So, get the signature right:
void Person::ChangeCar(Car * y)
{
car_ = y;
}
If you owned the pointers, you would need a destructor to tidy up pointers.
Tell whoever set wrote the code in main to delete their pointers!
Edit:
To re-iterate, in any of the Person you can call the methods on the meber variable car_ functions e.g.
void Person::ChangeCar(Car * y)
{
car_ = y;
y->PrintDriveKm(); //call a method on a car pointer.
car_->PrintDriveKm();
}
This is just the same as calling methods on pointers, as mentioned near the top of my answer.
Go back to
Car* dx = new Car("Toyota corolla DX", 25000);
// ...
Person* driver = new Person("James", dx);
From here, in main, you can call
dx->PrintDrivenKm();
From inside the Person constructor,
Person(string name, Car *car) : name_(name), car_(car)
{
}
You can call methods on car (or car_) inside the braces:
Person(string name, Car *car) : name_(name), car_(car)
{
std::cout << "Hello, " << name << '\n';
car_->PrintDrivenKm();
}
Of note: Car:: means something in the class/structr/namespace/scope Car - but you want to call instance methods, so need an instance name. Use -> to all methods on pointers to instances. Use . to call methods on instances.
Hi I need some clarification on some code since google did not help nor did any of my C++ books. Ok I have a base class,which I derived 2 other classes, but I did not post the code for them here since they don't have anything to do with my question:
ifndef BASEBALLPLAYER_H
#define BASEBALLPLAYER_H
#include <iostream>
using namespace std;
class BaseBallPlayer{ //abstract class meaning no instance can be made for it, which is why we access it via derived classes
//data members
protected:
string name;
int height;
int weight;
public:
BaseBallPlayer();
BaseBallPlayer(string nam, int wight, int hight);
string get_Name();
virtual void print_player()=0; //
virtual void load_player(ifstream & read) = 0; //
virtual ~BaseBallPlayer();
};
Then an ArrayList.h file:
#ifndef ARRAY_LIST_H
#define ARRAY_LIST_H
#include <string>
using namespace std;
const static int MAX_INIT = 99;
template <class elemType>
class ArrayList {
private:
int n_element;
elemType * data;
public:
~ArrayList();
ArrayList(int n = MAX_INIT);
ArrayList(const ArrayList<elemType> &);
const ArrayList<elemType> & operator=(const ArrayList<elemType> &);
void MakeEmpty();
bool IsFull() const;
int LengthIs() const;
void RetrieveItem(elemType &, bool&);
void InsertItem(elemType);
void DeleteItem(elemType);
void ResetList();
bool IsLastItem();
void GetNextItem(elemType &);
};
Now my question lies in this new class, its a standalone class, that I made in the PlayerDatabase.h file:
#ifndef PLAYERDATABASE_H
#define PLAYERDATABASE_H
#include <iostream>
#include "BaseBallPlayer.h"
#include "ArrayList.h"
using namespace std;
class PlayerDatabase{
private:
ArrayList<BaseBallPlayer *> teamArrayList; // I do NOT Understand what this means?
public:
};
#endif
I DO NOT understand what the private member in my PlayerDatabse.h file means or entails? And what can I do with it? My instructor told us to usethat template with a pointer but I didn't have a chance to ask what it does/mean?
So I'm not exactly sure what you end goal is here, but let me take a quick guess at what you might be trying to do:
So you mentioned you have 2 subclasses of BaseBallPlayer, let's say they are MajorLeaguePlayer and MinorLeagePlayer This private Array list teamArrayList can be used to hold any combinations of your base class (BaseBallPlayer -- in your case MajorLeaguePlayer and MinorLeaguePlayer).
You usually want to leave this teamArrayList private so that it will only be safely modified by your public methods. So for example you might want to have a constructor for PlayerDatabase that takes an argument of ArrayList<BaseBallPlayer *>
PlayerDatabase(ArrayList<BaseBallPlayer *> players) {
// set the private teamArray list in the constructor
teamArrayList = players;
}
or you might want to sort the teamArray list based off of one of the properties in the base class BaseBallPlayer
// or another one sorting for weight or name
void sortPlayerListByHeight() {
// sort the private team array list
teamArrayList = ... // sort by height
}
Maybe you want to get the number of players in the list, or find the first or last player in the list. In general it's good practice to use public methods to access/modify private data members (i.e. teamArrayList)
int numberOfPlayersInList() {
return teamArrayList.LengthIs();
}
BaseBallPlayer getFirstPlayerInList() {
return teamArrayList.RetrieveItem.... // get the first item in the list
}
Then from another class you could construct some of your subclass objects and construct your player database:
ArrayList<BaseBallPlayer *> playerList = new ArrayList<>();
playerList.add(new MinorLeagePlayer("minorName", 180,70);
playerList.add(new MajorLeaguePlayer("majorName", 200, 72);
PlayerDatabase db = new PlayerDatabase(playerList);
// now you can do some operations on the PlayerDatabase knowing that the list will contain all objects that can use methods from the Base Class (`BaseBallPlayer`)
db.getFirstPlayerInList().print_player(); // method from your base class implemented in your subclasses
int numberOfPlayers = db.numberOfPlayersInList();
// do something with the number of players in the list
This is pseudo code, but hopefully it will help you get the idea.
Edit related to our comments:
ArrayList<BaseBallPlayer *> *playerList = new ArrayList<BaseBallPlayer *>();
MinorLeaguePlayer *aPlayer = new MinorLeaguePlayer();
playerList->InsertItem(aPlayer);
I've included a couple of simple cout statements in the ArrayList constructor, the MinorLeaguePlayer constructor, and the InsertItem method to output some information when they are called (I'm assuming you already have implementations of these methods):
ArrayList constructor: n_element = n;
cout << "Constructing the arrayList, n_element = " << n_element << endl;
MinorLeaguePlayer constructor: cout << "Constructing a minor league player" << endl;
InsertItem method: cout << "Inserting an item into the ArrayList" << endl;
Here's the output after building and running the above code:
Constructing the arrayList, n_element = 99
Constructing a minor league player
Inserting an item into the ArrayList
Edit 2 related to further comments:
Methods which take a reference to the elemType
Example:
// this will basically just going to "hold" the BaseBallPlayer fetched
// from GetNextItem
BaseBallPlayer *bPlayer;
playerList->GetNextItem(bPlayer);
cout << "Weight after fetching from list = " << bPlayer->weight << endl;
The implementation of GetNextItem is going to look something like this:
void ArrayList<elemType>::GetNextItem(elemType& player) {
// implementation to get the next item in the array list
player = //... set the "NextItem" to the BaseBallPlayer reference we passed into this method
}
Edit 3: print_player() polymorphism:
MinorLeaguePlayer *minPlayer = new MinorLeaguePlayer();
MinorLeaguePlayer *min2Player = new MinorLeaguePlayer();
MajorLeaguePlayer *majPlayer = new MajorLeaguePlayer();
MajorLeaguePlayer *maj2Player = new MajorLeaguePlayer();
playerList->InsertItem(minPlayer);
playerList->InsertItem(min2Player);
playerList->InsertItem(majPlayer);
playerList->InsertItem(maj2Player);
BaseBallPlayer *fetchedPlayer;
for (int i = 0; i < 4; i++) {
playerList->GetNextItem(fetchedPlayer);
fetchedPlayer->print_player();
}
Notice that you have to get the reference to the fetchedPlayer prior to calling the print_player() method on it
playerList->GetNextItem(fetchedPlayer);
fetchedPlayer->print_player();
This is because of the way your GetNextItem method is structured to place the reference to the nextItem in the passed in BaseBallPlayer.
Here's another example where the method would return the BaseBallPlayer instead of setting it by reference:
method stub (in ArrayList):
elemType getNextItemReturn();
for loop:
for (int i = 0; i < 4; i++) {
playerList->getNextItemReturn()->print_player();
}
Here's a link to a quick discussion asking which is more efficient:
Which is more efficient: Return a value vs. Pass by reference?
And the output with the example cout statements:
Constructing the arrayList, n_element = 99
Inserting an item into the ArrayList
Inserting an item into the ArrayList
Inserting an item into the ArrayList
Inserting an item into the ArrayList
Printing From MINOR League Player
Player Name: MinorLeagueName Weight = 22
Printing From MINOR League Player
Player Name: MinorLeagueName Weight = 22
Printing From MAJOR League Player
Player Name: MajorLeaguePlayer Weight = 33
Printing From MAJOR League Player
Player Name: MajorLeaguePlayer Weight = 33
The mock implementations of print_player():
void MinorLeaguePlayer::print_player() {
cout << "Printing From MINOR League Player" << endl;
cout << "Player Name: " << name << " Weight = " << weight << endl;
}
void MajorLeaguePlayer::print_player() {
cout << "Printing From MAJOR League Player" << endl;
cout << "Player Name: " << name << " Weight = " << weight << endl;
}
teamArrayList is a list of pointers to BaseBallPlayer objects. By using pointers, it can by polymorphic -- the pointers can point to any class derived from BaseBallPlayer.
This is the common way to use an abstract base class. You can then use it to call the methods in the BaseBallPlayer class, and the implementations in the appropriate derived classes will be used.
I am a novice C++ programmer who is currently a student at my local University. I am doing this assignment and I am told to create a linked list of a class called Car, to create a "train". I have two derived classes which simply print differently.
What I want to do is create a list of train cars, and have two pointers pointing to the current Car of each type (Chair and Sleeping) so I know when the user wants to book a seat of a certain type within the train, I know exactly where to go there. When a train is full, the plan is to put a new train of that type onto the end. Ex: Sleeping Car's last seat is booked, a new Sleeping Car will be created and put at the end of the train. The current Sleeping Car pointer will now point to the new Car at the end of the list.
Below is the code I have for this program:
carTest.cc
int main()
{
int trainId = 0;
list<Car> train;
// Testing Car Default Constructor
// Testing Car Constructor
//cout << "Creating a \"Chair car\"... " << endl;
Car* currChair = nullptr, *currSleep = nullptr;
train.push_back(ChairCar(trainId++));
currChair = &train.back();
train.push_back(SleepingCar(trainId++));
currSleep = &train.back();
// Testing bookSeat
//book_seat_test(car2);
// Testing isTypeAvailable
//is_type_available_test(car2);
// Testing isBooked
//is_booked_test(car2);
// Testing mostAvailable
//most_available_test(car2);
// Testing firstAvailable
//first_available_test(car2);
// Testing getSeatNumber
///get_seat_number_test(car2);
// Testing getIndex
//get_index_test(car2);
// Testing bookFirstAvailable
//book_first_available_test(car2);
// Testing chairCar printStatus
//chairCar_print_status_test(*currChair);
// Testing sleepingCar printStatus
//sleepingCar_print_status_test(*currSleep);
currSleep = nullptr;
currChair = nullptr;
return 0;
}
car.h
class Car
{
public:
class Seat
{
public:
Seat() : row(-1), col(-1) {};
Seat(int i, int j) : row(i), col(j) {};
int getRow() const { return row; }
int getCol() const { return col; }
private:
int row;
int col;
};
public:
// Contructors
Car();
explicit Car(int, int, int);
// Deconstructor
~Car();
// Public Member Functions
bool bookSeat(int, int);
bool isTypeAvailable(int) const;
bool isBooked() const;
int mostAvailable() const;
int firstAvailable(int) const;
int getSeatNumber(int, int) const;
Seat getIndex(int) const;
int bookFirstAvailable(int);
virtual void printStatus(int) const;
protected:
int carNumber;
int rows;
int cols;
bool** plan;
int* numAvailable;
int columnSeperation;
void init();
};
car.cc
// function: Deconstructor
// Description:
// The Deconstructor simply frees the dynamically allocated memory
// of the data members plan and numAvailable if the members are not pointing
// to the nullptr.
Car::~Car()
{
if(plan != nullptr)
{
delete[] plan;
plan = nullptr;
}
if(numAvailable != nullptr)
{
delete[] numAvailable;
numAvailable = nullptr;
}
}
chairCar.h
class ChairCar : public Car
{
public:
ChairCar();
ChairCar(int);
protected:
void printStatus(int seatNumber) const;
};
#endif
chairCar.cc
#include "chairCar.h"
ChairCar::ChairCar()
: Car()
{
}
ChairCar::ChairCar(int id)
: Car(7,4,id)
{
}
void ChairCar::printStatus(int seatNumber) const
{
int maxSeatNumber = (rows-1)*cols+(cols-1);
if(seatNumber > maxSeatNumber || seatNumber < 0)
throw OutOfRangeException(seatNumber, 0, maxSeatNumber);
cout << setw(columnSeperation) << ' ' << " |";
cout << setw(columnSeperation) << "WL";
cout << setw(columnSeperation) << "ML";
cout << setw(columnSeperation) << "MR";
cout << setw(columnSeperation) << "WR";
cout << endl;
Car::printStatus(seatNumber);
}
Sleeping Car is exactly the same as Chair Car except different arguments are sent to the base constructor. When I run the code in the main function I get
Error in
`/home/w1llbedone/Programming/cpsc2620/assn/a4/carTest': double free or corruption (fasttop): 0x0000000000608010
I was trying to set the currCar pointers to nullptr before end of the scope to avoid this error. Can anyone explain to me why this happens? This is my first time posting on StackExchange, so I apologise for any lack of information. Any help would be greatly appreciated.
There are at least two major bugs in the partially-shown code. Bug #1:
list<Car> train;
// ...
train.push_back(ChairCar(trainId++));
This is a textbook case of object slicing. train is a std::list of Cars. The shown code constructs a ChairCar, and puts it into the list. This slices off the ChairCar subclass, and copies the Car superclass into the list.
Bug #2 is the primary bug here: this class violates the Rule Of Three. Car's destructor clearly deletes class members that were constructed in dynamic scope. However, the Car class does not define a copy constructor, nor the assignment operator. This pretty much rules out the chances of this class being Rule-of-three compliant.
So, these two bugs result in a lethal combination. During the initial object slicing, the temporary ChairCar object gets destroyed, but only after a copy of its Car superclass gets copy-constructed into the list's container. As part of the destruction, Car's destructor deletes its dynamically-scoped class members.
Then, eventually, the list container gets destroyed, and the sliced off Car, in the list, gets destroyed, and its destructor attempts to delete the pointers that were already deleted.
Game over.
I have a constructor inside a method that I want to have access at all time
//ItemEditor.cpp
#include "ItemContainer.h"
void ItemEditor::CreateItem() {
ItemContainer* wornItems = new ItemContainer();
}
inside of my driver I call my method createItem();
//driver
int main(){
ItemEditor* createItem = new ItemEditor();
createItem->CreateItem();
}
afterwards I want to have access to backpack outside of the createItem
How can I accomplish that?
Make the item container a member variable so its scope is the life time of the object.
There is no reason to use dynamic allocation, so just use an instance of the ItemContainer instead of a pointer.
#include <iostream>
class ItemContainer {
int item = 0;
public:
void addItem(int i) {
item = i;
}
int getItem() {
return item;
}
};
class ItemEditor {
public:
ItemEditor() {
}
void createEditor() {
wornItems.addItem(3);
}
ItemContainer wornItems;
};
int main() {
ItemEditor editor;
int item = editor.wornItems.getItem(); //or some method
std::cout << item << std::endl;
editor.createEditor();
item = editor.wornItems.getItem(); //or some method
std::cout << item;
return 0;
}
You can also make the container private and use public methods to access its contents. You can see an example here
By backpack I assume whatever is returned by
createItem->CreateItem();
Why not just store it in a pointer since you used the new to allocate the object in a heap?
ItemContainer* ItemEditor::CreateItem() {
return new ItemContainer();
}
Main file:
int main(){
ItemEditor* createItem = new ItemEditor();
ItemContainer* backpack = createItem->CreateItem();
}
Also I want to suggest it is a better practice to provide a move semantic for ItemContainer and get rid of pointers. That way you are relying on RAII and stack for object destruction, less risk of memory-leak. Related article:
http://www.cprogramming.com/c++11/rvalue-references-and-move-semantics-in-c++11.html
Here is a full compiling code:
//Header.h
#include <iostream>
class ItemContainer{
public:
void sayHello(){
std::cout << "HulloWorld!\n";
}
};
class ItemEditor{
public:
ItemEditor(){};
ItemContainer* ItemEditor::CreateItem(){
return new ItemContainer();
}
};
MainFile:
//main
#include "Header.h"
int main()
{
ItemEditor* createItem = new ItemEditor();
ItemContainer* backpack = createItem->CreateItem();
backpack->sayHello();
}