C++ dynamic_cast to subclass and trying to access to attribute - c++

I have following Classes:
class Vehicle
{
public:
Vehicle(int id);
virtual int getID() const;
virtual void setCustom(Customer* custom);
virtual Customer *getCustom() const;
virtual void printOnce() const = 0;
protected:
int id_;
Customer* custom_;
};
Vehicle::Vehicle(int id)
: id_{id}, custom_{nullptr}
{
}
class Car : public Vehicle
{
public:
Car(int id, int seats, string color);
virtual void printOnce() const override;
private:
int seats_;
int color_;
};
Car::Car(int id, int seats, string color)
: Vehicle(id), seats_{seats}, color_{color}
{
}
class Customer
{
public:
Customer(string customerName, int age, int driverlicenceType);
string getCustomerName() const;
private:
string customerName_;
int age_;
int driverlicenceType_;
};
Customer::Customer(string customerName, int age, int driverlicenceType)
: customerName_{customerName}, age_{age}, driverlicenceType_{driverlicenceType}
{
}
string Customer::getCustomerName() const
{
return customerName_;
}
and the following Method:
Vehicle *CarRental::findByName(string name)
{
auto cmp =[name](Vehicle* v){
if(v->getCustom() != nullptr) {
return name == v->getCustom()->getCustomerName();
}
};
//find Vehicle in vector <Vehicle*> vehicles_;
return (*find_if(vehicles_.begin(), vehicles_.end(), cmp));
}
Now I'm trying to get the Vehicle*, cast it to Car*, and test if the Customer is nullptr.
Code:
Vehicle* veh = findByName(name);
Car* c = dynamic_cast<Car*>(veh);
if(c->getCustom() == nullptr) {
//do anything
}
But somehow it isn't nullptr. If I try to get the name or age:
cout << "Customer: " << c->getCustom() << endl;
it shows me only Customer: (like an empty string). I think if it were nullptr this should not work and give me an error but I don't know why.

Related

C++ Inheritance of functions, passing in arguments

Base class : Employee
Derived class : Regular
Employee.cpp
void Employee::setValue(string id, string name, double s, int n)
{
empID = id;
empName = name;
salary = s;
}
Regular.cpp
void Regular::setValue(string id, string name, double s, int n)
{
annualLeave = n;
}
Employee::setValue() only stores the first 3 arguments passed in, but not int n, too.
I'm supposed to inherit that setValue() in Regular::setValue() and then just pass in the arguments, but this time store int n to annualLeave.
How do I do that?
Or, is there a way for me to set int n in the base class for the child class?
You can call the base class's implementation:
void Regular::setValue(string id, string name, double s, int n) {
annualLeave = n;
return Employee::setValue(std::move(id), std::move(name), s);
}
Otherwise, make base class polymorphic:
struct Employee {
void setValue(string id, string name, double s, int n) {
empID = std::move(id);
empName = std::move(name);
salary = s;
setLeave(n);
}
virtual ~Employee() {}
protected:
virtual void setLeave(int) = 0;
string empID;
string empName;
double salary;
};
struct Regular: Employee {
private:
void setLeave(int n) override { annualLeave = n; }
int annualLeave;
};
If necessary to keep a single-signature setValue function, it is possible to do it like that:
-
Includes:
#include <any>
#include <map>
#include <string>
-
Employee.h:
class CEmployee
{
protected:
virtual void setValue(std::map<std::string, std::any> &info);
int m_empID = 0;
std::string m_empName = {'\0'};
int m_salary = 0;
}
Employee.cpp:
void CEmployee::setValue(std::map<std::string, std::any> &info)
{
std::any item;
item = info["empID"];
if (item.has_value())
m_empID = std::any_cast<int>(item); // int
item = info["empName"];
if (item.has_value())
m_empName = std::any_cast<std::string>(item); // std::string
item = info["salary"];
if (item.has_value())
m_salary = std::any_cast<int>(item); // int
}
-
Regular.h:
class CRegular : public CEmployee
{
public:
void setValue(std::map<std::string, std::any> &info) override;
protected:
std::string m_annualLeave = {'\0'};
}
Regular.cpp:
void CRegular::setValue(std::map<std::string, std::any> &info)
{
std::any item;
CEmployee::setValue(info);
item = info["annualLeave"];
if (item.has_value())
m_annualLeave = std::any_cast<std::string>(item); // std::string
}
-
& call it like that:
void MyClass::HardcodedExample()
{
CRegular regular_employee;
std::map<std::string, std::any> info, update;
info["empID"] = { 100 };
info["empName"] = { std::string("Trump") };
info["salary"] = { 1000000 };
info["annualLeave"] = { std::string("29 Jul 2018") };
regular_employee.setValue(info); // Set all info
// Or:
update["annualLeave"] = { std::string("29 Dec 2018") };
regular_employee.setValue(update); // Update just "annualLeave"
// Or:
update["salary"] = { 1200000 };
update["annualLeave"] = { std::string("04 Jul 2018") };
regular_employee.setValue(update); // Update "salary" & "annualLeave"
}
-
Otherwise, setValue with 3 parameters to base-class, & with 4 parameters to the derived-class (that calls to the base-class with the 3 parameters and sets by itself the 4th one) - similar to what #RemyLebeauis offers - is a better solution.
-
& better to use #define / enum keys instead of string-keys (& change the key-type of the map accordingly), but this is a different issue.

Remove warning of deprecated conversion from string constant to 'char*

I have written a code like bill payment. Code is working fine but there are many warnings in my code which I want to remove. One of the most frequent warning is deprecated conversion from string constant to 'char* . I have tried many things and some of the warnings are gone but not all. Please anybody point out at my mistakes??
P.S: I have already tried replacing char* to const char* , but then I am not able to exchange or swap values and it was causing error. Any other solution??
Below is the code
#include<iostream>
#include<string.h>
using namespace std;
class item
{
private:
int barcode;
char* item_name;
public:
item (int num=0, char* name="NULL") : barcode(num)
{
item_name=new char[strlen(name)+1];
strcpy(item_name,name);
}
void setbarcode(int num)
{
barcode=num;
}
int getbarcode()
{
return barcode;
}
void scanner()
{
int num;
cin>>num;
setbarcode(num);
}
void printer()
{
cout <<"\nBarcode"<<"\t\t"<<"Item Name"<<"\t\t"<<"Price"<<endl;
cout <<barcode<<"\t\t"<<item_name<<"\t\t\t";
}
~item()
{
delete[]item_name;
}
};
class packedfood : public item
{
private :
int price_per_piece;
public :
packedfood(int a=0, int num=0, char* name = "NULL") : price_per_piece(a),item(num,name)
{
}
void setprice(int num)
{
price_per_piece=num;
}
int getprice()
{
return price_per_piece;
}
void scanner()
{
item::scanner();
}
void printer()
{
item::printer();
cout<<getprice()<<" Per Piece";
}
~packedfood()
{
}
};
class freshfood: public item
{
private:
int price_per_rupee;
float weight;
public:
freshfood(float b=0, int a=0,int num=0,char* name="NULL") : weight(b),price_per_rupee(a),item(num,name)
{
}
void setweight(float b)
{
weight=b;
}
int getweight()
{
return weight*50;
}
void printer()
{
item::printer();
cout<<getweight()<<" Per Rupee"<<endl<<endl;
}
void scanner()
{
item::scanner();
}
~freshfood()
{
}
};
int main()
{
item x(389,"Anything");
item y;
packedfood m(10,118,"Chocolate");
packedfood n;
freshfood r(20.9,93,357,"Fruits");
freshfood s;
cout <<"\n\n Enter the Barcode for Packed food : ";
m.scanner();
m.printer();
cout <<"\n\n Enter the Barcode for Fresh food : ";
r.scanner();
r.printer();
system("PAUSE");
return 0;
}

How can I check price of each sub class?

class Attraction {
};
class Museum : public Attraction {
private:
double price;
public:
void setPrice(double Price) {
price = Price;
}
double getPrice() {
return price;
}
};
class Park : public Attraction {
public:
double getPrice() {
return 0;
}
};
class Theatre : public Attraction {
private:
double price;
public:
void setPrice(double Price) {
price = Price;
}
double getPrice() {
return price;
}
};
int _tmain(int argc, _TCHAR* argv[]) {
vector<Attraction> attraction;
vector<Attraction>::iterator i;
for (i = attraction.begin(); i != attraction.end(); i++) {
if (i->getPrice() < 5) {
cout << endl;
}
}
}
vector<Attraction> performs object slicing, so you can never access getPrice() of derived classes. You need to use polymorphism instead, where you have a virtual double GetPrice() method in the Attraction class, and then use vector<Attraction*> with new/delete for the objects. Don't forget to make the destructor in Attraction virtual as well, so you can delete descendant object using a base pointer.
What you are attempting to do is not possible with the code you have shown. You are not utilizing polymorphism correctly.
Try something more like this instead:
class Attraction
{
public:
Attraction() {}
virtual ~Attraction() {}
virtual double getPrice(double Price)
{
return 0.0;
}
};
class PriceyAttraction : public Attraction
{
private:
double price;
public
PriceyAttraction(double Price = 0.0) : Attraction(), price(Price) {}
virtual double getPrice()
{
return price;
}
void setPrice(double Price)
{
price = Price;
}
};
class Museum : public PriceyAttraction
{
public:
Museum(double Price = 0.0) : PriceyAttraction(Price) {}
};
class Park : public Attraction
{
public:
Park() : Attraction() {}
};
class Theatre : public PriceyAttraction
{
public:
Theatre(double Price = 0.0) : PriceyAttraction(Price) {}
};
int _tmain(int argc, _TCHAR* argv[])
{
std::vector<Attraction*> attraction;
attraction.push_back(new Museum(5.00));
attraction.push_back(new Park);
attraction.push_back(new Theatre(7.50));
std::vector<Attraction*>::iterator i;
for (i = attraction.begin(); i != attraction.end(); ++i)
{
std::cout << i->getPrice() << std::endl;
//...
}
for (i = attraction.begin(); i != attraction.end(); ++i)
{
delete *i;
}
}
If you are using C++11 or later, you can use std::unique_ptr to manage the object deallocations for you:
int _tmain(int argc, _TCHAR* argv[])
{
std::vector<std::unique_ptr<Attraction>> attraction;
attraction.emplace_back(new Museum(5.00));
attraction.emplace_back(new Park);
attraction.emplace_back(new Theatre(7.50));
/* or:
attraction.push_back(std::unique_ptr<Attraction>(new Museum(5.00)));
attraction.push_back(std::unique_ptr<Attraction>(new Park));
attraction.push_back(std::unique_ptr<Attraction>(new Theatre(7.50)));
*/
/* or:
attraction.push_back(std::make_unique<Museum>(5.00));
attraction.push_back(std::make_unique<Park>());
attraction.push_back(std::make_unique<Theatre>(7.50));
*/
vector<Attraction>::iterator i;
for (i = attraction.begin(); i != attraction.end(); ++i)
{
std::cout << (*i)->getPrice() << std::endl;
//...
}
}

Class type arrays in other classes in C++

I have a problem with inputing values into arrays which are placed inside the class. I try to do this by using methods. My code looks like this:
#include <iostream>
using namespace std;
//class for items
class Item{
string name;
int amount;
public:
Item();
Item(string, int);
//returns the name of an item
string getName(){
return name;
}
//sets name for items
void setName(string name){
this->name = name;
}
//returns the amount of items
int getAmount(){
return amount;
}
//sets the amount for items
void setAmount(int amount){
this->amount = amount;
}
};
//first constructor
Item::Item(){
name="none";
amount=0;
}
//second constructor
Item::Item(string name, int amount){
this->name=name;
this->amount=amount;
}
//class for hero with "Items" array
class Hero{
string name;
Item inventory[20];
public:
Hero();
Hero(string);
//returns the name of the hero
string getName(){
return name;
}
//sets the name for the hero
void setName(string name){
this->name = name;
}
};
//first constructor
Hero::Hero(){
name="none";
}
//second constructor
Hero::Hero(string name){
this->name=name;
}
int main() {
Hero firsthero;
string name;
//giving hero the name
cout<<"Input name: ";
cin>>name;
firsthero.setName(name);
//printing the hero's name
cout<<firsthero.getName()<<endl;
//setting the items;
Item sword;
Item armor;
Item potion;
//setting items' values;
sword.setName("sword");
sword.setAmount(1);
armor.setName("armor");
armor.setAmount(1);
potion.setName("potion");
potion.setAmount(3);
//gives these items into array "inventory" in the "firsthero" class
return 0;
}
I would like to add items "sword", "armor" and "potion" into firsthero, however I have not found a way to write a method in "Hero" which would allow me to do that. I could just load them directly by making its fields public, but I read that it is not recommended.
Instead of having an array of size 20 in your Hero class, try using a std::vector. If you have a addItem method for Hero, you can simply do a check of whether or not the hero can hold anymore items (check inventory.size() against some constant you create, maybe something like MAX_INVENTORY_SIZE).
So something like this:
std::vector<Item> inventory;
const int MAX_INVENTORY_SIZE = 20;
...
//returns true if it successfully added the item, false otherwise
bool Hero::addItem(Item i) {
if(inventory.size < MAX_INVENTORY_SIZE) {
inventory.push_back(i);
return true;
}
return false;
}
...
hero.addItem(sword);
hero.addItem(armor);
hero.addItem(potion);
You need to write an accessor method for your items:
class Hero
{
private:
std::string name;
std::array<Item, 20> inventory; // use the array container instead of C-style arrays
unsigned int itemCount;
public:
Hero() : itemCount(0) {}
Hero(string n) : name(n), itemCount(0) {}
//returns the name of the hero
string getName()
{
return name;
}
//sets the name for the hero
void setName(const std::string& name)
{
this->name = name;
}
const Item& getItem(int i) const { return inventory[i]; } // NOTE: you may want some bounds checking here, but this is basically what you are doing
Item& getItem(int i) { return inventory[i]; } // to update a particular item
void addItem(const Item& item) { inventory[itemCount++] = i; } // same with bounds checking here
};

Adding two different Objects by overloading operator+ C++

I've been trying to figure out how to add a private member from Object A, to a private member from Object B.
Both Cat and Dog Class's inheriate from the base class Animal. I have a thrid class 'MyClass', that I want to inheriate the private members of the Cat and Dog class. So in MyClass, I have a friend function to overload the + operator. THe friend function is defined as follows:
MyClass operator+(const Dog &dObj, const Cat &cObj);
I want to access dObj.age and cObj.age within the above function, invoke by this statement in main:
mObj = dObj + cObj;
Here is the entire source for a complete reference into the class objects:
#include <iostream>
#include <vld.h>
using namespace std;
class Animal
{
public :
Animal() {};
virtual void eat() = 0 {};
virtual void walk() = 0 {};
};
class Dog : public Animal
{
public :
Dog(const char * name, const char * gender, int age);
Dog() : name(NULL), gender(NULL), age(0) {};
virtual ~Dog();
void eat();
void bark();
void walk();
private :
char * name;
char * gender;
int age;
};
class Cat : public Animal
{
public :
Cat(const char * name, const char * gender, int age);
Cat() : name(NULL), gender(NULL), age(0) {};
virtual ~Cat();
void eat();
void meow();
void walk();
private :
char * name;
char * gender;
int age;
};
class MyClass : private Cat, private Dog
{
public :
MyClass() : action(NULL) {};
void setInstance(Animal &newInstance);
void doSomething();
friend MyClass operator+(const Dog &dObj, const Cat &cObj);
private :
Animal * action;
};
Cat::Cat(const char * name, const char * gender, int age) :
name(new char[strlen(name)+1]), gender(new char[strlen(gender)+1]), age(age)
{
if (name)
{
size_t length = strlen(name) +1;
strcpy_s(this->name, length, name);
}
else name = NULL;
if (gender)
{
size_t length = strlen(gender) +1;
strcpy_s(this->gender, length, gender);
}
else gender = NULL;
if (age)
{
this->age = age;
}
}
Cat::~Cat()
{
delete name;
delete gender;
age = 0;
}
void Cat::walk()
{
cout << name << " is walking now.. " << endl;
}
void Cat::eat()
{
cout << name << " is eating now.. " << endl;
}
void Cat::meow()
{
cout << name << " says meow.. " << endl;
}
Dog::Dog(const char * name, const char * gender, int age) :
name(new char[strlen(name)+1]), gender(new char[strlen(gender)+1]), age(age)
{
if (name)
{
size_t length = strlen(name) +1;
strcpy_s(this->name, length, name);
}
else name = NULL;
if (gender)
{
size_t length = strlen(gender) +1;
strcpy_s(this->gender, length, gender);
}
else gender = NULL;
if (age)
{
this->age = age;
}
}
Dog::~Dog()
{
delete name;
delete gender;
age = 0;
}
void Dog::eat()
{
cout << name << " is eating now.. " << endl;
}
void Dog::bark()
{
cout << name << " says woof.. " << endl;
}
void Dog::walk()
{
cout << name << " is walking now.." << endl;
}
void MyClass::setInstance(Animal &newInstance)
{
action = &newInstance;
}
void MyClass::doSomething()
{
action->walk();
action->eat();
}
MyClass operator+(const Dog &dObj, const Cat &cObj)
{
MyClass A;
//dObj.age;
//cObj.age;
return A;
}
int main()
{
MyClass mObj;
Dog dObj("B", "Male", 4);
Cat cObj("C", "Female", 5);
mObj.setInstance(dObj); // set the instance specific to the object.
mObj.doSomething(); // something happens based on which object is passed in
dObj.bark();
mObj.setInstance(cObj);
mObj.doSomething();
cObj.meow();
mObj = dObj + cObj;
return 0;
}
If you want to access a private member of Dog, then your operator has to be a friend of Dog, not just a friend of some derived class of Dog.
If you add friend MyClass operator+(const Dog &dObj, const Cat &cObj); to the definition of class Cat and class Dog, then the function will have access to dObj.age and cObj.age.
Alternatively, you could add friend MyClass; to the definitions of class Cat and class Dog, but then all of MyClass's functions have access to all of Cat and Dog's internals.
Alternatively alternatively, you could make age protected rather than private.