How do I design a Strategy Pattern Class in C++ based on an UML Diagram? - c++

I'm designing a strategy pattern based on the following diagram:
I have to base the entire program on two things: the contents of the main function, and the Sale function getTotal() - which I was provided with;
Here's what I managed to write so far:
class Product {
private:
int code;
string type;
string description;
int price;
public:
Product(int code, string type, string description, int price): code{code}, type{type}, description{description}, price{price}{}
int getPrice() {
return price;
}
};
class SaleItem {
private:
Product product;
public:
int quantity;
Product getProduct() {
return product;
}
int getQuantity() {
return quantity;
}
};
class Sale {
public:
SaleItem s;
Sale(SaleItem s) : s{ s }{}
vector<SaleItem> items;
void additem(int n, Product p) {
items.push_back(s(n,p));
}
double getTotal();
};
class DiscountPolicy {
public:
virtual double getDiscount(const Sale* s, SaleItem si) = 0;
};
class CreditCardDiscount : public DiscountPolicy {
public:
virtual double getDiscount(const Sale* s, SaleItem si) {
return si.getQuantity() * si.getProduct().getPrice() * 0.02;
}
};
class NoDiscount : public DiscountPolicy {
public:
virtual double getDiscount(const Sale* s, SaleItem si) {
return si.getQuantity() * si.getProduct().getPrice() * 0.00;
}
};
double Sale::getTotal() {
double total = 0;
for (int i = 0; i < items.size(); i++) {
SaleItem sIt = items[i];
double price = sIt.getQuantity() * sIt.getProduct().getPrice();
//apply discount
price -= discountPolicy->getDiscount(this, sIt);
total += price;
}
return total;
}
int main() {
Sale s(new NoDiscount());
Product p1(1, "Apple", "food", 2.0);
Product p2(1, "TV", "electronics", 2000.0);
s.addItem(3, p1);
s.addItem(1, p2);
assert(s.getTotal() == 2006);
Sale s2(new CreditCardDiscount());
s2.addItem(3, p1);
s2.addItem(1, p2);
//total with discount for card
assert(s2.getTotal() == 1965.88);
}
I'm currently encountering two issues:
I can't wrap my head around designing the Sale class so that "Sale s(new NoDiscount());" and " Sale s2(new CreditCardDiscount());", from the main class, make sense.
I'm fairly certain there should be some code where the //apply discount comment is found in the getTotal() function, but I'm not sure how to implement it so that "price -= discountPolicy->getDiscount(this, sIt);" works.
The rest of the program should be implemented correctly, since I've seen similar designs, it's mainly the Sale function that I don't understand.
Appreciate the help!

Related

Easiest way for a child object to inherit all of parent object's data in C++?

I wanted to see if there is a way to set a child class object to inherit all the data from a parent class.
ex.
InventoryBook allBooks[20];
SoldBook child[0] = allBooks[0];
For context, I'm trying to write a program in C++ that keeps track of a hypothetical book store's inventory and I wanted to create a class that handles a sale transactions.
class BookData
{
protected:
char bookTitle[51] = {},
isbn[14] = {},
author[31] = {},
publisher[31] = {},
dateAdded[11] = {};
public:
void setTitle(char newTitle[]);
void setISBN(char newISBN[]);
void setAuthor(char newAuthor[]);
void setPub(char newPub[]);
char *getTitle();
char *getISBN();
char *getAuthor();
char *getPub();
char *getDateAdded();
bool bookMatch(char[]);
};
class InventoryBook : public BookData
{
protected:
int qtyOnHand;
double wholesale,
retail;
public:
void setDateAdded(char newDate[]);
void setQty(int newQty);
void setWholesale(double newWhole);
void setRetail(double newRetail);
int isEmpty();
void removeBook();
void delBook();
int getQty();
double getWholesale();
double getRetail();
};
class SoldBook : public InventoryBook
{
private:
const double taxRate = 0.06;
int qtySold;
double tax = 0, subtotal = 0;
static double total;
public:
SoldBook calcTax()
{
this->tax = qtySold * retail * taxRate;
return *this;
}
SoldBook calcSubtotal()
{
subtotal = (this->retail * qtySold) + tax;
return *this;
}
void setQtySold(int qty)
{
this->qtySold = qty;
}
int getQtySold()
{
return qtySold;
}
double getSubtotal()
{
return subtotal;
}
double getTotal()
{
return total;
}
InventoryBook getBook(InventoryBook book)
{
return book;
}
};
I wanted a SoldBook object to inherit all the data from InventoryBook without having to go to the extra trouble of creating a function that accepts the parent object as arguments and sets them in the child class ( SoldBooks )
ex.
void converter(char[] title, char[] isbn, ...etc)
{
this->bookTitle = title;
this->isbn = isbn;
etc...
}
Well I know how to do it the hard way but I just want the easiest way. Maybe something like
saleBooks[0] = allBooks[0];
do a constuctor take in the parent and member initialize it
public:
SoldBook(BookData bd)
:bookTitle(bd.title),
:isbn(bd.isbn),
:etc(etc),...
{}
then you can simply do
SoldBook soldBook = SoldBook(bd);
or create a vector for then
std::vector<SoldBook> soldBooks;
soldBooks.emplace_back(sb);
emplace back uses a constuctor call to avoid copying
and honestly i'd probably but the library into an unordered_map for easy key access

Passing a class object into a templated classes private member scope

Hi I'm new to c++ and trying to learn something. maybe it can't be done. but I want to:
create an Employee class that records all employees, and their information (see my code below).
Then I want to make a templated class for a linked list. inside the private scope of this class, I will have a "T data" type. I want my constructor to instantiate an "Employee" every time a LinkedList object is created in the main. I hope that makes sense. I have my code working the way I set it up now. However, I'm not necessarily templating it the way I want.
template <class T>
class Employees { //Parent
private:
int EmployeeID;
double Paycheck;
int Hours;
double Payrate;
std::string Employeename;
public:
Employees(int ID, double Prate, std::string EName) {
EmployeeID = ID;
Payrate = Prate;
Employeename = EName;
Hours = 0; //our constructor can just give each Employee 0 hours.
Paycheck = 0.00;
}
Employees() {
EmployeeID = 0;
Payrate = 0.0;
Employeename = "N/A";
Hours = 0;
Paycheck = 0.00;
}
void setPaycheck() {
std::cout << std::fixed;
std::cout << std::setprecision(2);
double i = Payrate;
i = i * 100;
i = i * Hours;
i = i / 100;
Paycheck = i;
//so I'm not sure why I couldn't just cast the double, but the complier kept rounding down each time.
// I had to make a conversion of my decimal into a whole number and then go back and divide it to get the
// paycheck amount.
};
void setEMPname(std::string Name) {
Employeename = Name;
}
void setPayrate(double payrate) {
Payrate = payrate;
}
void setEMPid(int IDnum) {
EmployeeID = IDnum;
}
void setHOURS(int hours) {
Hours += hours;
}
int IDReturn() { return EmployeeID; }
int HoursReturn() { return Hours; }
double PaycheckReturn() { return Paycheck; }
double PayrateReturn() { return Payrate; }
std::string NameReturn() { return Employeename; }
};
template <class T>
class LinkedLists :Employees<T> { //child
friend class Employees<T>;
private:
////I want change the object below to "T data"
Employees<T> EmployeeObject; //contains all the employee information
LinkedLists<T>* nextlink;
LinkedLists<T>* prevlink;
public:
LinkedLists() {
EmployeeObject;
nextlink = nullptr;
prevlink = nullptr;
}
void setname(std::string Name) {
EmployeeObject.setEMPname(Name);
}
void setPrate(double payrate) {
EmployeeObject.setPayrate(payrate);
}
void setid(int IDnum) {
EmployeeObject.setEMPid(IDnum);
}
void setPayCheck() { EmployeeObject.setPaycheck(); }
LinkedLists<T>*& setLinkforward() {
return nextlink;
}
LinkedLists<T>*& setLinkbackward() {
return prevlink;
}
int idReturn() { return EmployeeObject.IDReturn(); }
double payrateReturn() { return EmployeeObject.PayrateReturn(); }
std::string nameReturn() { return EmployeeObject.NameReturn(); }
void AddHours(int Hours) { EmployeeObject.setHOURS(Hours); }
int ReturnHours() { return EmployeeObject.HoursReturn(); }
double ReturnPayCheck() {
return EmployeeObject.PaycheckReturn();
}
};

Saving all the derived balance into parent balance

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();
}

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;
//...
}
}

Define a class student with the following specification (remaining que below)

I dont understand why i am not getting total.
The question is
Define a class student with the following specification:Private
members of class student admno integer sname 20 character eng.
math, science float total float ctotal() a function to calculate eng +
math + science with float return type. Public member function of
class student Takedata() Function Public member function of class
student Takedata() Function float ctotal() a function to calculate
eng + math + science with floa return type. Public member function
of class student Takedata() Function
#include<stdio.h>
#include<iostream>
using namespace std;
class Student
{
private:
int admno;
char sname[20];
float english,maths,science;
float total;
float ctotal()
{
total=(english+maths+science);
return(total);
}
public:
void Takedata()
{
cout<<"Enter the value of admno:";
cout<<" sname :";
cout<<"eng :";
cout<<"science:";
cout<<"maths:";
cin>>admno;
cin>>sname;
cin>>english;
cin>>science;
cin>>maths;
}
Student(): total(0.0) //constructor
{
}
friend float func(Student);
void Showdata()
{
cout<<"adm no:"<<admno;
cout<<"sname:"<<sname;
cout<<"eng"<<english;
cout<<"science"<<science;
cout<<"maths"<<maths;
}
};
float func(Student t)
{
t.total;
return t.total;
}
int main()
{
Student s1;
s1.Takedata();
s1.Showdata();
cout<"total is:";
cout<<func(s1);
}
Need to make either total or method ctotal() public.
Then call either one of them from
public:
float total;
float func(Student t)
{
t.total;
return t.total;
}
OR
public:
float ctotal() {
total=(english+maths+science);
return(total);
}
float func(Student t)
{
return t.ctotal();
}
func should be defind like this
float func(Student t)
{
return t.ctotal();
}
also edit
cout<"total is:";
to
cout<<"total is:";
Replace t.total with t.ctotal() in
float func(Student t)
{
t.total;
return t.total;
}