-1

I'm trying to figure out how queues work in C++ and am getting stuck when dealing with objects. I seem to only be able to get a return address instead of the name of the object (which is what I really want). It's also showing an error when I try to pop the element from the queue. My code is as follows:

Buyer.h file

#ifndef BUYER_H
#define BUYER_H
#include <string>
#include <queue>
#include "Order.h"
#include "Entity.h"
#include "Seller.h"

class Order;

class Seller;

class Buyer : public Entity {

public:
 Buyer(const std::string &, const std::string &, double);
 virtual ~Buyer() { }; // when step is added make this virtual
 void addSeller(Seller *);
 std::queue<Seller*> getSellers() const;
 void addOrder(Order *);
 std::queue<Order*> getOrders() const;
 virtual void list() const override;
 virtual void step() const override;

private:
 std::queue<Order*> orders;
 std::queue<Seller*> sellers;

};
#endif

Buyer.cpp file

#include <iostream>
#include <ostream>
#include <stdexcept>
#include <string>
#include <queue>
#include "Buyer.h"
#include "Seller.h"
#include "Order.h"
#include "Entity.h"
using namespace std;

Buyer::Buyer(const std::string &name, const std::string &id, double balance)
  : Entity(name, id, balance)
{
  // initialize seller and order queue??
} // Constructor

void Buyer::addSeller(Seller *s) {
  sellers.push(s);
} // addSeller

std::queue<Seller*> Buyer::getSellers() const {
  while(!sellers.empty()) {
    return sellers;
  } // while
} // getSellers

void Buyer::addOrder(Order *o) {
  orders.push(o);
} // addOrder

std::queue<Order*> Buyer::getOrders() const {
  while(!orders.empty()) {
    return orders;
  } // while
} // getOrders

void Buyer::list() const {
  Entity::list();
  std::cout << "Orders:\nOrder contains:";
  std::cout << "\nSellers:\n";
  int i = 0;
  while(!sellers.empty()) {
    std::cout << sellers.front() << "\n";
    sellers.pop();
  } // while
} //list

void Buyer::step() const {
  std::cout << "\nstep enter\n"
            << "step exit\n\n";
} // step

Any help is appreciated! Thank you!

user3337808
  • 11
  • 1
  • 4
  • possible duplicate of [How to "return an object" in C++?](http://stackoverflow.com/questions/3350385/how-to-return-an-object-in-c) – aruisdante May 04 '14 at 15:47

1 Answers1

1

(This isn't a full answer but it is too big to go in a comment)

It's OK to return std::queue<Order *>, and so on. However, you need to be clear on who owns the objects being pointed to; i.e. who is responsible for deleting them.

When you return a std::queue<Order *>, what happens is that the returned queue is a copy of the original one, however all the pointers point to the same object that the original one pointed to . (This is a sort of "shallow copy").

If you then delete anything in the returned queue, you will cause the original queue to malfunction because it will be accessing deleted memory.

As such, this is a fragile design because the caller can easily cause the object to screw up despite the fact that getOrders is a const function.

One "solution" is to make the containers contain shared_ptr<Order> instead of Order *. Then everything happens automatically; the caller can add or delete to his heart's content.

If it is not strictly necessary for the containers to contain pointers, consider using containers of objects: std::queue<Order>. The benefit of this approach is that the default copy and move semantics are all correct.

Another approach to consider is having getOrders() and getSellers() return a const reference, instead of returning a copy of the queue.

NB. In Buyer::getSellers(), and getOrders() if it is empty then you fall off the end of the function without returning, causing undefined behaviour. You need to either return something (what's wrong with returning an empty queue?) or throw an exception.

M.M
  • 138,810
  • 21
  • 208
  • 365