I know this question has already been asked, but none of the answers that I have as of yet found seem to suffice. I am creating a vector of pointers to a base class and adding all sorts of derived classes to it. Now, the base class has a virtual function that is overridden in all of the derived classes and that is unique to each of them. So, when I go through the vector and retrieve those objects and call the function on that object, I need it to call the right one, but all it will do is call the base class version. I am even trying to cast the individual elements back to their original class when I retrieve them from the vector but they refuse to be cast! e.g.
vector<base*> myBase;
DerivedClass *myDerived = static_cast<DerivedClass> myBase[i];
This doesn't work, despite the fact that everything I've read suggests that it should. My debugger says that despite all of this, myDerived is still of type base and it's version of my virtual function is being called.
Any ideas?
class BankAccount {
public:
BankAccount(string namein, string typein){
name = namein;
type = typein;
balance = 0;
}
virtual string getType();
virtual void printTransactions() = 0;
virtual int withdraw(double amt){
return getBalance() -amt;
}
};
class SavingsAccount: public BankAccount {
public:
SavingsAccount(string namein, string typein);
void addTransaction(string transType, string name);
virtual int withdraw(double amt);
void printTransactions();
virtual string getType();
private:
};
SavingsAccount::SavingsAccount(string namein, string typein): BankAccount(namein, typein) {
}
int SavingsAccount::withdraw(double amt){
double aBal = getBalance() - amt;
if (aBal > 0){
setBalance(aBal);
}
return getBalance() - amt;
}
class CheckingAccount: public SavingsAccount {
public:
CheckingAccount(string nameIn, string typein): SavingsAccount(nameIn, typein){
}
virtual int withdraw(double amt);
void printTransactions();
string getType(){
return "Checking";
}
};
int CheckingAccount::withdraw(double amtIn){
double newBal = getBalance() - amtIn;
if (newBal < 500.00 && newBal > 2.49) {
setBalance(newBal - 2.50);
}
return newBal;
}
int main(int argc, const char * argv[])
{
vector<BankAccount*> myAccts;
SavingsAccount *mySav;
CD *myCD;
CheckingAccount *myCheck;
switch (option) {
case 1: {
string name;
string type;
cout << "Enter name: ";
cin >> name;
getline(cin, dump);
cout << "Enter account type: ";
cin >> type;
getline(cin, dump);
if (type.compare("Checking") == 0) {
CheckingAccount myCheck1 = CheckingAccount(name, type);
myAccts.push_back(&myCheck1);
}
case 3:{
for (int x = 0; x < myAccts.size(); x++) {
if (myAccts[x]->getName() == name && myAccts[x]->getType() == type) {
if (type == "Savings") {
mySav = static_cast<SavingsAccount*>(myAccts[x]);
double y = mySav->withdraw(amt);
if (y < 0){
cout << "Insufficient funds!";
}
}
if (type == "Checking") {
myCheck = myAccts[x]->GetDerived();
double y = myCheck->withdraw(amt);
if (y < 0){
cout << "Insufficient funds!";
}
if (y < 497.5) {
cout << "Withdrawal fee: $ 2.50" << endl;
}
}
}
Checking Account is a child of Savings Account. Sorry.
Your concept is correct and shouldn't require any casting. The whole point of virtual functions is that if you're holding a base class pointer or reference and call a virtual function, the most derived version of this function will be called at runtime.
The error I see is this:
if (type.compare("Checking") == 0) {
CheckingAccount myCheck1 = CheckingAccount(name, type);
myAccts.push_back(&myCheck1);
You are creating a checking account on the stack, then taking it's address and pushing that address into the vector. At the end of the if block myCheck1 will go out of scope and be destroyed. Your vector will have an address to a location in the stack and you will have Undefined Behavior.
Instead do:
if (type.compare("Checking") == 0) {
myAccts.push_back(new CheckingAccount(name, type));
And similar for the other types. Get rid of all of those casts. In this version you will have to delete all of the items in the vector at the end. If you use a std::vector<std::unique_ptr<BankAccount>> then the unique_ptr will take care of cleaning up your allocated objects.
You need to use new to create your accounts... you have:
if (...)
{
CheckingAccount myCheck1 = CheckingAccount(name, type);
myAccts.push_back(&myCheck1);
}
...myCheck1 gets destroyed when leaving that if scope, leaving myAccts with a pointer to an effectively random location on the stack that has undefined behaviour if accessed. Change to:
if (type == "Checking")
myAccts.push_back(new CheckingAccount(name, type));
You will then need to have matching deletes for the vector elements. Googling "C++ new delete tutorial" would be a good idea. The next stage is to learn how to use smart pointers, for example - std::shared_pointer - which remove the burden of remembering to delete.
"Case 3" can be corrected/simplified to:
for (int x = 0; x < myAccts.size(); x++)
if (myAccts[x]->getName() == name && myAccts[x]->getType() == type) {
double y = myAccts[x]->withdraw(amt);
if (y < 0)
cout << "Insufficient funds!";
if (type == "Checking" && y < 497.5)
cout << "Withdrawal fee: $ 2.50" << endl;
}
Notice in particular the double y = myAccts[x]->withdraw(amt); - the virtual function makes sure the right version is called without you having to do anything type-specific in the calling code.
Have you tried something like this?
class base
{
public:
inline DerivedClass *GetDerived() {return (DerivedClass*)this;}
...
};
DerivedClass *myDerived = myBase[i]->GetDerived();
Related
Why pointer to pointer has been used rather than single pointer in the code? Also do you think the destructor was written wrong if it is how can i make it correct?
pointer to pointer: employee** _arr;
You can see the code below:
#include<iostream>
class employee {
private:
std::string _name;
std::string _surname;
int _year;
double _salary;
static int numberOfEmployees;
public:
employee() {
_name = "not-set";
_surname = "not-set";
_year = 0;
_salary = 0;
numberOfEmployees++;
}
employee(int year, std::string name, std::string surname) {
_name = name;
_surname = surname;
_year = year;
numberOfEmployees++;
calculateSalary();
}
void calculateSalary() {
//salary = 2310 + 2310 * year * 12/100.0
_salary = 2310 + (2310 * (double)_year) * (12 / 100.0);
}
void printInfo() {
std::cout << _name << " " << _surname << " " << _year << " " << " " << _salary << " TL/month" << std::endl;
}
static int getEmployeeCount() {
return numberOfEmployees;
}
};
class employeeList {
private:
int _size;
int _lenght;
employee** _arr;
public:
employeeList() :_size(1), _lenght(0), _arr(NULL) {}
employeeList(int size) :_size(size) {
_arr = new employee * [_size];
_lenght = 0;
}
int listLength() {
return _lenght;
}
employee retrieve_employeeFromIndex(int index) {
if (index >= 0 && index < _size) {
return *_arr[index];
}
}
void addToList(employee* item) {
_lenght++;
if (_lenght <= _size) {
_arr[_lenght - 1] = item;
}
else {
std::cout << "you cannot add another employee!";
}
}
static void printEmployees(employeeList el) {
for (int i = 0; i < el._lenght; i++) {
el._arr[i]->printInfo();
}
}
~employeeList() {
delete[] _arr;
}
};
int employee::numberOfEmployees = 0;
int main() {
employee a;
employee b(5, "John", " Doe");
employee c(3, "Sue", "Doe");
employeeList empList(employee::getEmployeeCount());
empList.addToList(&a);
empList.addToList(&b);
empList.addToList(&c);
employeeList::printEmployees(empList);
std::cout << empList.listLength() << std::endl;
return 0;
}
you can see the output:
Why pointer to pointer has been used rather than single pointer in the code? Also do you think the destructor was written wrong if it is how can i make it correct?
Why pointer to pointer was used in the code?
This is known only by the author who wrote the code. We can make a reasonable guess that their intention may have been to:
Allocate a dynamic array of objects, using a bare pointer to the first element of that array.
Indirectly point to objects stored elsewhere, hence they wanted to use an array of pointers, thus a pointer to first element of the array is a pointer to a pointer.
Their choice 1. to use an owning bare pointer is unnecessary, and there are better choices available which do not require an owning bare pointer. Most commonly, std::vector would be used to create a dynamic array.
Their choice 2. to indirectly point to objects that aren't owned by the class instance is not quite as safe as having the class instance own the objects, but regardless that may have been a reasonable choice depending on the reasons they chose this design. It is impossible to tell whether the choice was good without documentation of what the program is supposed to do. Based on the generic name of the class, I suspect that it wasn't a good choice.
do you think the destructor was written wrong
It can be considered correct. There are other issues with the class though.
The entire employeeList class seems pointless, and can easily be replaced by a std::vector. printEmployees is the only member function that wouldn't be directly provided by a vector. You can use a non-member function for that instead.
Im not expert but u will bumb your topic :P
I think that question is not precised. You mean that pointer to pointer:?
employee** _arr;
Because is pointing a pointer:
_arr = new employee * [_size];
I think that it have sense because array is a pointer? I can be wrong ofcourse coz I just started do educate.
Why do you think destruktor is wrong? It's deleting a pointer.
I have a base class (robot) and depending on the arguments passed to the program I want to downcast the robot pointer to a specific derived class. the robot class has virtual functions which are defined in each of the derived classes.
So far I can create a pointer of the base class, and within a conditional statement, create a derived class which the base is then dynamically cast to. Within the conditional the pointer works as intended but after leaving the conditional statement the derived class is out of scope and the functions go back to virtual. Is there a way I can keep the pointer to the derived class?
class vehicles{
public:
virtual void print_state(int state_ind, ofstream& file){}
};
class hovercraft : public vehicles{
public:
hovercraft(
int L_in, int W_in,
double start_x, double start_y,
double goal_x, double goal_y)
{
L = L_in;
W = W_in;
start_state.x = start_x;
start_state.y = start_y;
goal_state.x = goal_x;
goal_state.y = goal_y;
Tree.push_back(start_state);
}
void print_state(int state_ind, ofstream& file){
state s = Tree[state_ind];
file<<s.phi<<","<<
s.u<<","<<
s.v<<","<<
s.r<<","<<
s.x<<","<<
s.y<<"\n";
}
private:
struct state{
double g=0;
double u=0;
double v=0;
double r=0;
double x=0;
double y=0;
double phi=0;
int p=0;
};
int L,W;
state start_state, goal_state, state_sample;
vector<state> Tree;
};
int main(int argc, char* argv[])
{
ifstream infile;
string vehicle_name;
vehicles* vehicle;
int start, goal;
for(int i=0; i < argc; i++){
if (string(argv[i])=="-m"){
infile.open (argv[i+1]);
} else if (string(argv[i])=="-v"){
vehicle_name = string(argv[i+1]);
}
}
ofstream file_out;
file_out.open ("state.csv");
if(vehicle_name == "hovercraft"){
int L, W;
double start_x, start_y, goal_x, goal_y;
infile >> L;
infile >> W;
infile >> start_x;
infile >> start_y;
infile >> goal_x;
infile >> goal_y;
hovercraft my_vehicle(L,W, start_x, start_y, goal_x, goal_y);
hovercraft* vehicle = dynamic_cast<hovercraft*>(&my_vehicle);
} else {
cout<<"Invalid Vehicle: "<<vehicle_name<<"\n Exiting...\n";
return 0;
}
vehicle->print_state(0);
}
This is simplified from the actual code but I think it captures the issue. The result I want is for print to work the same inside the if statement and after it but after it will always print "no vehicle".
You're overloading the variable rptr inside the scope of your if-statements, which hides the one declared at the top of main. Your final rptr->print() is therefore undefined behavior, because you're calling a virtual function on an uninitialized pointer.
Simply remove the overloading as follows:
robot *rptr = nullptr;
if (*argv[1] == 'h') // <-- also fixed this (yours was broken)
{
rptr = new hovercraft();
rptr->print();
}
else if (*argv[1] == 'q') // <-- also fixed this (yours was broken)
{
rptr = new quadrotor();
rptr->print();
}
else
{
std::cout << "Invalid vehicle input" << std::endl;
}
if (rptr)
{
rptr->print();
}
You might also want to consider using std::shared_ptr or std::unique_ptr (along with std::make_shared or std::make_unique) to correctly manage the lifetime of dynamic memory.
This a menu based program to create a database of people and for performing operations on their name. After compilation, I am able to add a person successfully using the add function of Person class but when I retrieve the list of the added people using list function it shows garbage values instead of showing the entered names. It's the question no. 4(lab 4) in the below give doc.
https://drive.google.com/open?id=18cR9bgPlqM6q-kXBIcxg5Hpj04bkZMnW&authuser=0
#include<iostream>
#include<stdio.h>
#include<string.h>
#include<stdlib.h>
using namespace std;
class Person
{
const char *name;
public:
Person(const char* n)
{
name=n;
}
bool search(const char* substr)
{
const char *str=name;
while(*str!='\0')
{ int count=0;
if(*str==*substr)
{ const char *s=substr;
const char *p=str;
while(*s!='\0')
{
if(*p==*s)
{
count++;
p++;
s++;
}
else
break;
}
}
if(count==strlen(substr))
{
cout<<name<<endl;
return true;
}
str++;
}
return false;
}
void print()
{
cout<<name<<endl;
}
~Person()
{
cout << ":)";
}
friend class People;
};
class People
{
Person** array;
int length;
void prompt()
{
cout << "\n'A'-Add a person\n'L'-List all persons\n'S'-Search\n'Q'-Quit\n";
}
public:
People()
{
array = NULL;
length = 0;
}
void add()
{
string m;
cout << "Enter a Name:\n";
cin >> m;
Person s(m.c_str());
if (array == NULL)
array = (Person**)malloc(sizeof(Person*));
else
{
array=(Person**)realloc(array, length*sizeof(Person*));
}
array[length] =new Person(s.name);
array[length]->print();
++length;
}
void list()
{
cout << "\nThe names of the person in the list are:\n";
for (int i = 0; i <length; i++)
{
array[i]->print();
}
}
void search()
{
string a;
int flag = 0;
cout << "\nEnter a string to be found in the names present in the list:\n";
cin >> a;
cout << "\n The names with entered substring are:\n";
for (int i = 0; i <length; i++)
{
bool state=array[i]->search(a.c_str());
if (state)
flag = -1;
}
if (flag == 0)
cout << "\nNone of the names contains the entered substring!!!\n";
}
void menu()
{
char c = 'Y';
while (c != 'Q')
{
cout << "Choose an option(character):\n";
prompt();
cin>>c;
switch (c)
{
case 'A':add();
cout << "Name entered sucessfully!!!\n";
break;
case 'L':list();
break;
case 'S':search();
break;
case 'Q':c = 'Q';
break;
}
}
}
};
int main()
{
People All;
All.menu();
return 0;
}
I am not able to find any mistake in my implementation of add function. What could be the possible reason for malfunctioning of list function?
tl;dr
You store a pointer to the internal memory of string (m). That string gets destroyed at the end of add() so you have pointer to unallocated memory, which causes undefined behaviour.
possible solutions
Best would be to store a std::string instead of a const char * inside Person.
walkthrough
If you want a more detailed analyses: You store a pointer to a string that goes out of scope.
void add()
{
string m; // string is initialized and allocates memory for its content
cout << "Enter a Name:\n";
cin >> m; // read content
Person s(m.c_str()); // m.c_str() retrieves a pointer to the memory allocated by m
//this pointer is stored inside s
if (array == NULL)
{
array = (Person**)malloc(sizeof(Person*));
}
else
{
array=(Person**)realloc(array, length*sizeof(Person*));
}
array[length] = new Person(s.name); // s.name still points to the memory allocated by m
array[length]->print();
++length;
} //At the end of the function m gets destroyed and deallocates its memory
So after the function exits you still have stored the pointer to m.c_str() inside a persons name. This pointer now points to unallocated memory. This memory now may (or may not) be overwritten at any time. You get undefined behaviour and print garbage.
In my header file I have:
class Game
{
private:
string _name;
Level _currentLevel;
public:
Game();
~Game();
void setName();
void run();
};
In my cpp file I have my run function:
void Game::run()
{
bool finished = false;
string input;
while (!finished)
{
// get input
std::cout << "Enter a command: \n";
std::getline(std::cin, input);
if (input == "quit")
{
finished = true;
}
else if (input == "new")
{
Level _currentLevel;
}
else if (input == "print")
{
_currentLevel.printMap();
}
else
{
std::cout << "Unknown command! \n";
}
}
}
constructor and printmap method of Level
Level::Level()
{
_width = RandomGenerator::Instance()->getRandom(6, 10);
_height = RandomGenerator::Instance()->getRandom(6, 10);
for (int y = 0; y < _height; y++)
{
for (int x = 0; x < _width; x++)
{
addRoom(x, y);
}
}
}
void Level::printMap()
{
for (int y = 0; y < _height; y++)
{
for (int x = 0; x < _width; x++)
{
if (x != 0)
cout << " - ";
cout << _map[coordinate(x, y)].getSize();
}
cout << "\n";
}
}
However when I type new, that runs Level _currentLevel; (to create a new non pointer object), the object dosnt change. I can see it dosn't change the values of level when I run printmap (which prints a map with 30 random values created in the Level constructor). While debugging the value of _height changes in the Level constructor. How should the value of _currentLevel be updated from my Game class?
Your new block creates a local stack variable that happens to have the same name as your instance variable (_currentLevel). It does not overwrite the instance variable, and that's why nothing changes.
You have a few straightforward choices:
Use a pointer. I suggest using a shared_ptr so you don't have to worry about deallocating memory on your own.
Extend Level to have an Initialize function. The constructor can call this, or you can call it from other code later if you want to re-initialize an existing variable.
Copy a new local variable to the instance variable.
Personally, I'd suggest the pointer, but either works.
For starters the prototypes should be in the header and the implementation in the source file. Apart from that, in game::run you declare a second local _currentlevel which shadows the class variable. Outside the constructor, you never modify the class field.
Replace the shadowing line with this->_currentlevel = Level();
I am trying to make one class work with another class. It is supposed to decrement the member of the other class.
my first class is
class Bike
{
private:
int miles;
Speedometer speedom;
static int fuelCount;
public:
Bike();
Bike(int, Speedometer*); //Problem occurs here
~Bike();
int getMiles();
int getFuelCount();
void incrementMiles();
};
int Bike::fuelCount = 0;
Bike::Bike()
{
miles = 0;
fuelCount++;
}
Bike::Bike(int m, Speedometer * spm) //This is where I am having problems
{
miles = m;
speedom = &spm;
}
Bike::~Bike()
{
cout << "The Bike's destructor is running." << endl;
fuelCount--;
}
int Bike::getMiles()
{
return miles;
}
int Bike::getFuelCount()
{
return fuelCount;
}
void Bike::incrementMiles()
{
miles++;
if (miles == 999999)
miles = 0;
}
The other class which is supposed to be included in the first is:
Class Speedometer
{
private:
int fuel;
public:
Speedometer();
Speedometer(int);
~Speedometer();
int getFuel();
void incrementFuel();
void decrementFuel();
};
Speedometer::Speedometer()
{
fuel = 0;
}
Speedometer::Speedometer(int f)
{
fuel = f;
}
int Speedometer::getFuel()
{
return fuel;
}
void Speedometer::incrementFuel()
{
if (fuel <= 15)
fuel++;
}
void Speedometer::decrementFuel()
{
if (fuel > 0)
fuel--;
}
They are supposed to work together. Bike is to be able to work with speedometer object. It should decrease the speedometers current amount of fuel by one gallon for every 24 miles traveled.
This is supposed to be a aggregate relationship not composition.
Please help me just understand how to make that relationship and how its supposed to be called.
Thank you in advance.
here is my main function
btw - i have all the right #includes i just have not listed them here
int main(int argc, char *argv[])
{
Speedometer a(999970, spd);
for(int count = 0; count <=24; count++)
a.decrementMiles();
while (a.getFuel() > 0)
{
a.incrementMiles();
cout<< "Miles:" << a.getMiles() << endl;
cout<< "Fuel:" << a.getFuel() << endl;
}
return 0;
}
You have a large number of issues here.
First of all, in your main(), you construct your Speedometer object with a constructor you have not implemented. The only constructors you have defined are the default constructor and Speedometer(int). You then call Speedometer(int, ???), the ??? being spd because you do not declare spd anywhere in the code you have provided, so we have no idea what it is.
It's really impossible to say what's wrong with your code in its current state.
As written, you've made a composition; Speedometer is part of Bike since it is a field. To make it an aggregation, make Bike hold a pointer to Speedometer. Note that as a consequence, you'll probably need Bike to create or obtain an initial Speedometer (could be NULL to begin with, or pass one in the constructor), and you might want to add accessor methods to Bike in order to add/remove/change the Speedometer.
[edit] Bike might also need to know how to dispose of the Speedometer properly in order to avoid leaking it.
[edit 2] Also as #cjm571 pointed out, your main function is creating and operating directly upon a "disembodied" Speedometer. Shouldn't it be on a Bike? :)
#include <iostream>
using namespace std;
class Bike
{
private:
int miles;
static int fuelCount;
// Speedometer speedom;
public:
Bike();
Bike(int); // Speedometer *); check comment on line 82
~Bike();
int getMiles();
int getFuelCount();
void incrementMiles();
};
int Bike::fuelCount = 0;
Bike::Bike()
{
miles = 0;
fuelCount++;
}
Bike::Bike(int m)//Speedometer (*spm) I don't see the purpose of this in the current state of the program, I may not be seing the whole picture
{
miles = m;
/* speedom = spm; remember, there must be a parent and a child class, at the current state you'r trying
to call a child from parent, the child class has not been defined, so i switched them and now Bike is a chiled. */
}
Bike::~Bike()
{
cout << "The Bike's destructor is running." << endl;
fuelCount--;
}
int Bike::getMiles()
{
return miles;
}
int Bike::getFuelCount()
{
return fuelCount;
}
void Bike::incrementMiles()
{
miles++;
if (miles == 999)
miles = 0;
}
class Speedometer
{
private:
int fuel;
public:
Speedometer();
Speedometer(int f);
int getFuel();
Bike theBike; // This is what you needed in order to make incrementMiles to work.
void incrementFuel();
void decrementFuel();
};
Speedometer::Speedometer()
{
fuel = 0;
}
Speedometer::Speedometer(int f)
{
fuel = f;
}
int Speedometer::getFuel()
{
return fuel;
}
void Speedometer::incrementFuel()
{
if (fuel <= 15)
fuel++;
}
void Speedometer::decrementFuel()
{
if (fuel > 0)
fuel--;
}
int main(int argc, char *argv[])
{
Speedometer a(999); //You never declared this, did you mean spm???
for(int count = 0; count <=24; count++)
a.theBike.incrementMiles();
while (a.getFuel() > 0)
{
a.theBike.incrementMiles();
cout<< "Miles:" << a.theBike.getMiles() << endl;
cout<< "Fuel:" << a.getFuel() << endl;
}
cin.get();
return 0;
} //There is no break declared (that i can see at least) so the program runs an infinite loop
// Don't want to add too many things to it, I don't know what your plan is.
// Hoping to have made it clearer.