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;
//...
}
}
Related
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.
In my function 'func' i want to create an object Menu who returns a breakfast with lemon and coffee. 'func' return a list of menu
When I try to display the menu for a breakfast that contains only lemon or only coffee it is displayed correctly. For example:
c.push_back(make_unique<Breakfast>("eggs", 10));
but when i try to display a menu that also contains lemon and coffee it shows me error in main
this is the program:
#include <iostream>
#include <vector>
using namespace std;
class Menu {
private:
int price;
public:
Menu(int p = 0) : price{ p } {}
virtual string description() = 0;
virtual int getPrice() {
return price;
}
virtual ~Menu() {}
};
class WithLemon : public Menu {
private:
Menu* meniu;
public:
WithLemon(Menu* n) :
meniu{ n } {}
string description() override {
return meniu->description() + " with lemon ";
}
int getPrice() override {
return meniu->getPrice() + 4;
}
};
class WithCoffee : public Menu {
private:
Menu* meniu;
public:
WithCoffee(Menu* n) :
meniu{ n } {
}
string description() override {
return meniu->description() + " with coffee ";
}
int getPrice() override {
return meniu->getPrice() + 5;
}
};
class Breakfast : public Menu {
private:
string name;
public:
Breakfast(string n, int p) :
name{ n }, Menu{ p } {
}
string description() override {
return name;
}
};
std::vector<std::unique_ptr<Menu>> func(void)
{
std::vector <std::unique_ptr<Menu> > c;
Breakfast a{ "breakfast eggs", 10 };
WithCoffee breakfast_with_coffee{ &a };
Menu* breakfast_with_coffee_and_lemon = new WithLemon{ &breakfast_with_coffee };
//cout << breakfast_with_coffee_and_lemon->description() << " " << breakfast_with_coffee_and_lemon->getPrice();// print ----> breakfast eggs with coffee with lemon 19
c.push_back(make_unique<WithLemon>(&breakfast_with_coffee));
return c;
}
int main() {
std::vector < std::unique_ptr<Menu> > lista = func();
for (int i = 0; i < lista.size(); i++) {
cout << lista[i]->description() << " " << lista[i]->getPrice() << endl; //error read memory access
}
return 0;
}
You can't take a pointer to automatic memory, store it in a smart pointer and leave the function. After you leave the function the automatic memory is freed and the smart pointer contains a dangling pointer. The simplest way to avoid this problem and other problems with memory leaks is to use smart pointers for all variables:
#include <iostream>
#include <memory>
#include <string>
#include <vector>
class Menu {
private:
int price;
public:
Menu(int p = 0) : price{ p } {}
virtual std::string description() = 0;
virtual int getPrice() {
return price;
}
virtual ~Menu() = default;
};
class WithLemon : public Menu {
private:
std::unique_ptr<Menu> meniu;
public:
WithLemon(Menu* n) : meniu{ n } {}
std::string description() override {
return meniu->description() + " with lemon ";
}
int getPrice() override {
return meniu->getPrice() + 4;
}
};
class WithCoffee : public Menu {
private:
std::unique_ptr<Menu> meniu;
public:
WithCoffee(Menu* n) :
meniu{ n } {
}
std::string description() override {
return meniu->description() + " with coffee ";
}
int getPrice() override {
return meniu->getPrice() + 5;
}
};
class Breakfast : public Menu {
private:
std::string name;
public:
Breakfast(std::string n, int p) : Menu{ p }, name{ n } {}
std::string description() override {
return name;
}
};
std::vector<std::unique_ptr<Menu>> func(void) {
std::vector <std::unique_ptr<Menu> > c;
auto a = std::make_unique<Breakfast>("breakfast eggs", 10);
auto breakfast_with_coffee = std::make_unique<WithCoffee>(a.release());
//Menu* breakfast_with_coffee_and_lemon = new WithLemon{ breakfast_with_coffee };
//std::cout << breakfast_with_coffee_and_lemon->description() << " " << breakfast_with_coffee_and_lemon->getPrice();// print ----> breakfast eggs with coffee with lemon 19
c.push_back(std::make_unique<WithLemon>(breakfast_with_coffee.release()));
return c;
}
int main() {
std::vector < std::unique_ptr<Menu> > lista = func();
for (const auto &i : lista) {
std::cout << i->description() << " " << i->getPrice() << std::endl; //error read memory access
}
return 0;
}
Avoid raw new and delete. Avoid pointers to automatic memory.
I have been practicing creating bankaccount class with 3 derived classes.
I was wondering how I could get lumsum amount of all three derived classes into parent balance as how a bank statement shows total net amount of all the different kind of accounts related to a user account.
should I just make separate a function to reconcile all three with get_Balance func and setbalance? or with using inheritance there is something I can do without creating the func?
#include "pch.h"
#include <iostream>
#include <vector>
using namespace std;
class bankaccount {
int accountnum;
double balance;
public:
//bankaccount() { accountnum = 0; balance = 0.00; }
bankaccount(int newacctnum) :accountnum(newacctnum) { balance = 1000.00; }
int getacctnum() { return accountnum; }
double getbalance() { return balance; }
void set_balance(double x) { balance = x; }
void deposit(double deposits) { balance += deposits; }
void withdraw(double minus) { balance -= minus; }
virtual void runMonthly() { balance = balance; };
};
class CheckingAccount:public bankaccount {
int fee;
public:
CheckingAccount(int acctnum, int newfee) :bankaccount(acctnum) { fee = newfee; };
void runMonthly() { set_balance(getbalance() - fee); }
};
class SavingsAccount:public bankaccount {
double interest;
public:
//SavingsAccount() { interest = 0.00; }
SavingsAccount(int acctnum, double newint) :bankaccount(acctnum) { interest = newint; };
void runMonthly() { set_balance(getbalance() *(1.00+ interest)); }
};
class CreditCard :public bankaccount {
double cardint;
public:
//CreditCard() { cardint = 0.00; }
CreditCard(int acctnum, double newint) :bankaccount(acctnum) { cardint = newint/100; }
void runMonthly() { set_balance(-1*getbalance() *(1.00 + cardint)); }
};
class Bank {
vector<bankaccount*>thelist;
public:
void addAccount(bankaccount *accounts){
thelist.push_back(accounts);
}
void runMonthly() {
thelist[0]->deposit(60000);
for (int i = 0; i < thelist.size(); i++)
thelist[i]->runMonthly();
for (int i = 0; i < thelist.size(); i++) {
cout << thelist[i]->getacctnum() << " " << thelist[i]->getbalance() << endl;
}
}
};
int main() {
Bank b;
b.addAccount(new bankaccount(122552));
b.addAccount(new CheckingAccount(12345, 18)); //$18 monthly fee
b.addAccount(new SavingsAccount(12346, 0.02)); // 2% per month interest!
b.addAccount(new CreditCard(12347, 21.5)); // 21.5% interest rate!
b.runMonthly();
}
The key insight, in my opinion, is to realize that the Parent Account is not actually a parent account.
In my code below, each customer will have one BaseAccount instead of the parent account in your code. (Although for more advanced banking, multiple customers may have access to a single account.)
You cannot withdraw() or deposit from a BaseAccount. Instead, the BaseAccount just holds all the sub-accounts.
NOTE: This virtual inheritance is relatively slow. The code will end up doing a lot of pointer chasing. Better alternatives to runtime polymorphism (== virtual inheritance) are CRTP and std::variant. I did not want to deviate from the shown original code, too much.
Result: https://godbolt.org/z/WjWMe-
#include <algorithm>
#include <cassert>
#include <iostream>
#include <memory>
#include <numeric>
#include <vector>
class BankAccount {
int accountnum;
double balance;
public:
BankAccount(int newacctnum) : accountnum(newacctnum), balance(0.0) {}
virtual ~BankAccount(){};
int getAccountNumber() { return accountnum; }
double getBalance() { return balance; }
void set_balance(double x) { balance = x; }
void deposit(double deposits) { balance += deposits; }
void withdraw(double minus) { balance -= minus; }
virtual void consolidateMonthly() = 0; // Better name than runMonthly
};
class CheckingAccount : public BankAccount {
int fee;
public:
CheckingAccount(int acctnum, int newfee) : BankAccount(acctnum) {
fee = newfee;
};
void consolidateMonthly() final { set_balance(getBalance() - fee); }
};
class SavingsAccount : public BankAccount {
double interest;
public:
SavingsAccount(int acctnum, double newint) : BankAccount(acctnum) {
interest = newint;
};
void consolidateMonthly() final {
set_balance(getBalance() * (1.00 + interest));
}
};
class CreditCard : public BankAccount {
double cardint;
public:
CreditCard(int acctnum, double newint) : BankAccount(acctnum) {
cardint = newint / 100;
}
void consolidateMonthly() final {
set_balance(-1 * getBalance() * (1.00 + cardint));
}
};
class BaseAccount { // NOTE: Purposefully not inheriting from a 'BankAccount' as
// deposit,withdraw do not make sense.
public:
BaseAccount(int account_number) : account_number_(account_number){};
void addSubsidiaryAccount(std::unique_ptr<BankAccount> account) {
sub_accounts_.push_back(std::move(account));
}
std::vector<std::tuple<int, double>> getSubAccountStatements() const {
std::vector<std::tuple<int, double>> ret;
ret.push_back({account_number_, getBalance()});
for (const auto &account : sub_accounts_) {
ret.push_back({account->getAccountNumber(), account->getBalance()});
}
return ret;
}
void consolidateMonthly() {
for (auto &account : sub_accounts_) {
account->consolidateMonthly();
}
}
int getAccountNumber() const { return account_number_; }
int getBalance() const {
return std::accumulate(
sub_accounts_.begin(), sub_accounts_.end(), 0.,
[](double balance, const std::unique_ptr<BankAccount> &acc) {
return balance + acc->getBalance();
});
}
BankAccount *getAccount(int account_number) const {
auto act =
std::find_if(sub_accounts_.begin(), sub_accounts_.end(),
[account_number](const std::unique_ptr<BankAccount> &ptr) {
return ptr->getAccountNumber() == account_number;
});
return act != sub_accounts_.end() ? act->get() : nullptr;
}
private:
const int account_number_;
std::vector<std::unique_ptr<BankAccount>> sub_accounts_;
};
class Bank {
std::vector<std::unique_ptr<BaseAccount>> account_list;
public:
void addAccount(std::unique_ptr<BaseAccount> account) {
account_list.push_back(std::move(account));
}
void runMonthly() const {
for (const auto &account : account_list) {
account->consolidateMonthly();
auto sub = account->getSubAccountStatements();
for (auto [acct, balance] :
sub) { // Requires "structured bindings" from C++17
std::cout << acct << ": " << balance << "\n";
}
}
}
void deposit(BankAccount *account, double amount) {
assert(account);
account->deposit(amount);
}
};
int main() {
Bank bank;
// First, let's have a base_account and add all the subsidiary accounts to
// this base account.
auto base_account = std::make_unique<BaseAccount>(122552);
base_account->addSubsidiaryAccount(
std::make_unique<CheckingAccount>(12345, 18));
base_account->addSubsidiaryAccount(
std::make_unique<SavingsAccount>(12346, 0.02)); // 2% per month interest!
base_account->addSubsidiaryAccount(
std::make_unique<CreditCard>(12347, 21.5)); // 21.5% interest rate!
auto checking_account_ptr = base_account->getAccount(12345);
if (!checking_account_ptr) {
std::cerr << "Failed to find account with ID 12345!\n";
return -1;
}
// Deposit 60k into the checking account(12345)
checking_account_ptr->deposit(60000);
bank.addAccount(std::move(base_account));
bank.runMonthly();
}
I have to use the Decorator pattern, based on an UML diagram. Depending on the type of string I input, I have to return a price and a description. The issue I'm encountering is that the UML description strictly specifies that the price function is not virtual, and furthermore, it should only be implemented in the Smoothy interface, as shown below in the code:
#include<iostream>
using namespace std;
class Smoothy{
int price;
public:
int getPrice(){
return price;
}
virtual ~Smoothy() = default;
virtual string description() = 0;
};
class BasicSmoothy: public Smoothy{
private:
string nume;
public:
BasicSmoothy(string n): nume(n){}
string description(){
return nume;
}
};
class SmoothyDecorator:public Smoothy{
private:
Smoothy *b;
public:
SmoothyDecorator(Smoothy* bb){
b = bb;
}
~SmoothyDecorator(){
delete b;
}
string description(){
return b->description();
}
};
class SmoothyWithCream:public SmoothyDecorator{
public:
SmoothyWithCream(Smoothy *b):SmoothyDecorator(b){
}
string description(){
return SmoothyDecorator::description() + " with Cream!";
}
};
class SmoothyWithCinnamon:public SmoothyDecorator{
public:
SmoothyWithCinnamon(Smoothy *b):SmoothyDecorator(b){
}
string description(){
return SmoothyDecorator::description() + " with Cinnamon!";
}
};
int main(){
Smoothy* b = new SmoothyWithCinnamon(new BasicSmoothy("Kiwi"));
cout<<b->description();
}
I'm pretty sure my code reflects the Decorator pattern(plese let me know if it doesn't), but I'm not sure how to return the price, based on the string. In addition to that, the UML diagram specifies that the BasicSmoothy has two types, with two specific prices(Kiwi 10$, Strawberry 12$) and the Derived classes each add 2$ and 3$ to the final listed price.
Is there a way to return the price through the function getPrice() without it being virtual and without implementing it in the other classes?
You can make the price protected and overwrite it in the decorator:
#include<iostream>
using namespace std;
class Smoothy{
protected:
int price;
public:
int getPrice(){
return price;
}
virtual ~Smoothy() = default;
virtual string description() = 0;
};
class BasicSmoothy: public Smoothy{
private:
string nume;
public:
BasicSmoothy(string n): nume(n) {
if (nume == "Kiwi") {
price = 10;
} else if (nume == "Strawberry") {
price = 12;
} else {
throw;
}
}
string description(){
return nume;
}
};
class SmoothyDecorator:public Smoothy{
private:
Smoothy *b;
public:
SmoothyDecorator(Smoothy* bb){
b = bb;
}
~SmoothyDecorator(){
delete b;
}
string description(){
return b->description();
}
};
class SmoothyWithCream:public SmoothyDecorator{
public:
SmoothyWithCream(Smoothy *b):SmoothyDecorator(b){
price = b->getPrice() + 2;
}
string description(){
return SmoothyDecorator::description() + " with Cream!";
}
};
class SmoothyWithCinnamon:public SmoothyDecorator{
public:
SmoothyWithCinnamon(Smoothy *b):SmoothyDecorator(b) {
price = b->getPrice() + 3;
}
string description(){
return SmoothyDecorator::description() + " with Cinnamon!";
}
};
int main(){
Smoothy* b = new SmoothyWithCinnamon(new BasicSmoothy("Kiwi"));
cout<<b->description() << std::endl;
cout << b->getPrice();
}
For anyone curios, I managed to find the solution.
class Smoothy
{
public:
Smoothy()
{
}
Smoothy(int n):
price(n)
{
};
virtual ~Smoothy() = default;
int getPrice()
{
return price;
}
virtual string description() = 0;
private:
int price;
};
class BasicSmoothy :
public Smoothy
{
public:
BasicSmoothy(string n) :
Smoothy(n=="Kiwi"?10:12),
nume(n)
{
}
string description()
{
return nume;
}
private:
string nume;
};
class SmoothyDecorator :
public Smoothy
{
public:
SmoothyDecorator(Smoothy* bb, int pret) :
Smoothy(pret + bb->getPrice()), b(bb)
{
}
~SmoothyDecorator()
{
delete b;
}
string description()
{
return b->description();
}
private:
Smoothy* b;
};
class SmoothyWithCream :
public SmoothyDecorator
{
public:
SmoothyWithCream(Smoothy* b) :
SmoothyDecorator(b, 2)
{
}
virtual string description()
{
return SmoothyDecorator::description() + " with Cream!" + to_string(getPrice());
}
};
class SmoothyWithCinnamon :
public SmoothyDecorator
{
public:
SmoothyWithCinnamon(Smoothy* b) :
SmoothyDecorator(b, 3)
{
}
virtual string description()
{
return SmoothyDecorator::description() + " with Cinnamon!" + to_string(getPrice());
}
};
int main()
{
Smoothy* b1 = new SmoothyWithCinnamon(new SmoothyWithCream(new BasicSmoothy("Kiwi")));
Smoothy* b2 = new SmoothyWithCinnamon(new SmoothyWithCream(new BasicSmoothy("Strawberry")));
cout <<b1->description() << std::endl;
cout <<b2->description() << std::endl;
delete b1;
delete b2;
}
I have the following code:
class ISubscriber;
class News {
public:
float getVersion() { return this->version; }
void setVersion(float state) { this->version= state; this->notifyAllSubscribers(); }
void attach(ISubscriber *observer) { this->subscribers.push_back(observer); }
void notifyAllSubscribers() {
for (vector<ISubscriber*>::iterator it = subscribers.begin(); it != subscribers.end(); it++){
(*(*it)).update();
}
}
private:
vector<ISubscriber*> subscribers;
float version;
};
class ISubscriber {
public:
News *news;
virtual void update() = 0;
};
class Subscriber1 : public ISubscriber {
public:
Subscriber1(News *news) { this->news = news; this->news->attach(this); }
void update() override { cout << "Subscriber1: A new version of the newspaper has been launched (v" << this->news->getVersion() << ")" << endl; }
};
class Subscriber2 : public ISubscriber {
public:
Subscriber2(News *news) { this->news = news; this->news->attach(this); }
void update() override { cout << "Subscriber2: A new version of the newspaper has been launched (v" << this->news->getVersion() << ")" << endl; }
};
int main(int argc, char *argv[]) {
News newspaper;
newspaper.setVersion(2.1f);
Subscriber1 sb1(&newspaper);
Subscriber2 sb2(&newspaper);
return 0;
}
But strange errors happened:
The first error points to this code (*(*it)).update(); in news class.
Why that errors happened, what's the reason?
(*(*it)).update(); requires the type ISubscriber to be complete, just the forward declaration is not enough.
You could move the defnition of ISubscriber before the one of News, and give a forward declaration of News before that.
class News;
class ISubscriber {
public:
News *news;
virtual void update() = 0;
};
class News {
public:
float getVersion() { return this->version; }
void setVersion(float state) { this->version= state; this->notifyAllSubscribers(); }
void attach(ISubscriber *observer) { this->subscribers.push_back(observer); }
void notifyAllSubscribers() {
for (vector<ISubscriber*>::iterator it = subscribers.begin(); it != subscribers.end(); it++){
(*(*it)).update();
}
}
private:
vector<ISubscriber*> subscribers;
float version;
};