0

i have a base class product and a child class multiBuyProduct

class Product
{
public:
  Product(std::string name, Amount price);
}


class MultiBuyProduct :public Product
{
public:
MultiBuyProduct(std::string aName, Amount price, int minDiscountedQuantity, int  discountedPercent);

now obviously some of the constructor variables are the same but in my main class i assume if i want the functionality of multiBuyProduct i need to call it? or can i call product and pass values for the multiBuyProduct constructor into a parameter that is expecting a product?

Below shows a method where this is used

void ShoppingCart::add(Product p, int quantity, bool end)
{
}  

Above is the method i want to sent the parameters to but i dont know if i need to change the code for this method to accept a MultiBuyProduct or ...??

EDIT: sorry forgot to mention 'Amount' is a class that takes two integers

    Amount amount(0,1);

3 Answers 3

1

You should change ShoppingCart::add something like below, to achieve polymorphic behavior:

void ShoppingCart::add(Product *p, int quantity, bool end)
{
  p->doSomething();
  // ...
  Product *product = p;
  product->doSomething();
  // ...
}

Usage:

ShoppingCart shoppingCart;

MultiBuyProduct multiBuyProduct("Paper", Amount(0,1), 1, 1);

shoppingCart.add(&multiBuyProduct, 1, true);
Sign up to request clarification or add additional context in comments.

7 Comments

thanks this looks like what i need, iv done this but in my method add, how do i use p? im putting Product product = p; then using p.doSomething(); for example but it just says i cant do product = p; no binary operator found ??
oh ok needed to be Product product = *p; no errors now however using methods from this just isnt returning anything at all now. product.getPrice(); should retun the price of that product that was passed in main but instead just does nothing
Use should use p in this way: p->doSomething().
@AngryDuck: Use product as I wrote in the answer.
thanks for the example thats working great :) the method in the child class is running and giving an expected result, my only problem is that this method on child class will run and return a price with a discount depending on whether enough have been added to shopping cart to get a discount, if enough havent been added then i want to call the normal getPrice() function from parent class product am i right in thinking i do that like this return Product::getPrice(quantity);
|
1

You will probably want to add a virtual method in Product, say, Amount Product::calculatePrice(int quantity), and override it in MultiBuyProduct so that it performs the correct calculation based on minDiscountedQuantity. Then, call this method from add(). Furthermore, you need to pass a reference (Product&) or a pointer (Product*) to add() in order for virtual method invocation to work.

9 Comments

thanks but i really dont know enough to really understand that, shall i post more code?
@AngryDuck: An explanation of virtual methods will be too long for this post, so you need to read up on it. However, the core idea is that when you have a virtual method in a base class, the subclasses may replace the method with their own code so that the behaviour will be different in the subclasses. If you have a pointer to a Product and call a virtual method on it, C++ will figure out what kind of object the pointer really points to and invoke the proper method (so even if you don't know that you actually have a MultiBuyProduct, you'll get the correct price calculation).
nice one thanks for the little explanation i get it now, i was just unclear on the c++ terminology, its basically is the c++ way of just overriding a method like in java with the @override tag :P
@AngryDuck: Yes; virtual methods in C++ work just like regular methods in Java (or rather, methods in Java are virtual by default). Also, in C++, pure virtual method means the same as abstract method in Java.
thanks for the info @Aasmund its good to know things in relation to java as im new to c++ but have a fair amount of experience in java, always makes things eaiser when you can relate them to something you know
|
0

You should change a few things.

You need a type of pointer or reference for polymorphic behaviour.

You need to call the base class constructor.

You need to override your virtual methods.

You should watch out for proper memory management once you rely on pointers.

You should try to be const correct.

Consider this example below:

#include <string>
#include <iostream>
#include <vector>
#include <memory>
#include <sstream>

class Product
{
private:
  double Price;
  std::string Name;

public:
  Product(const std::string& name, double price)
    : Price(price),
      Name(name)
  {
    std::cout << "Created " << name << " for $" << price << std::endl;
  }

  virtual std::string GetName() const
  {
    return Name;
  }

  virtual double GetPrice() const
  {
    return Price;
  }
};

class MultiProduct :public Product
{
private:
  int Quantity;

public:
  MultiProduct(const std::string& name, double price, int quantity)
    : Product(name, price),
      Quantity(quantity)
  {
    std::cout << "Created " << quantity << "x " << name << " for $" << price << " each." <<  std::endl;
  }

  virtual double GetPrice() const
  {
    return Product::GetPrice() * Quantity;
  }

  virtual std::string GetName() const
  {
    std::stringstream s;

    s << Product::GetName();
    s << " x";
    s << Quantity;

    return s.str();
  }
};

class ShoppingCart
{
private:
  std::vector< std::shared_ptr<Product> > Cart;

public:
  void Add( std::shared_ptr<Product> product )
  {
    Cart.push_back( product );
  }

  void PrintInvoice() const
  {
    std::cout << "Printing Invoice:" << std::endl;

    for( auto it = Cart.begin() ; it != Cart.end() ; ++it )
    {
      std::cout << (*it)->GetName() << ": " << (*it)->GetPrice()  << std::endl;;
    }
  }
};

int main()
{
  ShoppingCart cart;

  cart.Add( std::shared_ptr<Product>( new Product( "cheese", 1.23 ) ) );
  cart.Add( std::shared_ptr<Product>( new MultiProduct( "bread", 2.33, 3 ) ) );
  cart.Add( std::shared_ptr<Product>( new Product( "butter", 3.21 ) ) );
  cart.Add( std::shared_ptr<Product>( new MultiProduct( "milk", 0.55, 5 ) ) );
  cart.Add( std::shared_ptr<Product>( new Product( "honey", 5.55 ) ) );

  cart.PrintInvoice();

  std::cout << "Press any key to continue" << std::endl;
  std::cin.get();

  return 0;
}

4 Comments

thank but this really isnt constructive, i appriciate the long detailed reply but im not about to tear down like 4 classes and completely remake them when people having given answers that didnt do this
Well, if you experience problems later on with the seemingly simpler solutions, feel free to return here and have a look at this answer before asking a new question. The other answers seem simpler because they expect you to already know that their changes imply that you need to make other changes in your program. If you don't, it will crash sooner or later. If you do, you end up with what you called tearing down 4 classes.
thank you but my class structure is fine i have 4 classes each doing functions for a particular purpose all i wanted to do was extend the functionality of product to add discounts when buying a set number of them i dont think this entails rewriting 4 classes, i also dont think its fair to say the simpler / easy ways to do in an insulting manor these answers above are simply more appropriate
This is just an example. I cannot compile something on a few headers alone, so I had to make up some class bodies. You don't need to copy them verbatim. That was never the intention. The intention is to have a complete, compilable example to show all the features you need. Polymorphism, Pointers, virtual methods, calling base class constructors.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.