-1

My code is as shown below. The problem is inside the int main() function, r.printItems() is not printing anything. What am I missing here?

main.cpp

#include <bits/stdc++.h>
#include "Customer.h"
#include "MenuCreator.h"
#include "FoodItem.h"

MenuCreator m1;

void createCustomer() {
    Customer c1("mrg", "m@gmail.com", "9654357", "+91");
}

void createRestaurantItem(Restaurant &rest) {
    rest.addItems(FoodItem("t1"));
    rest.addItems(FoodItem("D1"));
}

void createMenu() {
    m1.createMenu("sg");
    Category c1;
    c1.setName("Non-veg");
    m1.addCategory(c1);
    Restaurant r1;
    r1.setName("ABC");
    r1.setDescription("Test Restaurant");
    createRestaurantItem(r1);
    c1.addRestaurants(r1);
}

vector<Restaurant> getRestaurantsForCategory(string category) {
    return m1.getRestaurantsForCategories(category);
}


int main() {
    createCustomer();
    createMenu();
    for (auto r: getRestaurantsForCategory("Non-veg")) {
        r.printItems();
    }
    return 0;
}

MenuCreator.h

#include <bits/stdc++.h>
#include "Menu.h"

using namespace std;

class MenuCreator {

public:

    void createMenu(string name) {
        Menu m1;
        m1.setName(name);
        menu = m1;
    }

    void addCategory(const Category &categ) {
        categories.push_back(categ);
    }

    const Menu &getMenu() const {
        return menu;
    }

    const vector<Category> &getCategories() const {
        return categories;
    }

    void addRestaurantForCategory(string name, const Restaurant restaurant) {
        for(auto categ: categories) {
            if (categ.getName() == name) {
                categ.addRestaurants(restaurant);
            }
        }
    }

    const vector<Restaurant> &getRestaurantsForCategories(string category) {
        for(auto categ: categories) {
            if(categ.getName() == category) return categ.getRestaurants();
        }
    }

private:
    Menu menu;
    vector<Category> categories;
};

Menu.h

#include<bits/stdc++.h>
#include "Category.h"

using namespace std;

class Menu {
public:
    const string &getName() const {
        return name;
    }

    void setName(const string &name) {
        Menu::name = name;
    }

private:
    string name;
    string description;
    vector<Category> categories;
};

Category.h

using namespace std;

class Category {
public:
    const string &getName() const {
        return name;
    }

    void setName(const string &name) {
        Category::name = name;
    }

    const string &getDescription() const {
        return description;
    }

    void setDescription(const string &description) {
        Category::description = description;
    }

    const vector<Restaurant> &getRestaurants() const {
        return restaurants;
    }

    void setRestaurants(const vector<Restaurant> &restaurants) {
        Category::restaurants = restaurants;
    }

    void addRestaurants(const Restaurant &rt) {
        Category::restaurants.push_back(rt);
    }

private:
    string name;
    string description;
    vector<Restaurant> restaurants;
};

FoodItem.h

#include <bits/stdc++.h>
#include <vector>
#include "FoodItem.h"

using namespace std;

class Restaurant {
public:

    Restaurant() {
        this->id = gen_random(12);
    }

    virtual ~Restaurant() {

    }

    const string &getName() const {
        return name;
    }

    void setName(const string &name) {
        Restaurant::name = name;
    }

    const string &getDescription() const {
        return description;
    }

    void setDescription(const string &description) {
        Restaurant::description = description;
    }

    double getLat() const {
        return lat;
    }

    void setLat(double lat) {
        Restaurant::lat = lat;
    }

    double getLang() const {
        return lang;
    }

    void setLang(double lang) {
        Restaurant::lang = lang;
    }

    const string &getImageUrl() const {
        return imageUrl;
    }

    void setImageUrl(const string &imageUrl) {
        Restaurant::imageUrl = imageUrl;
    }

    const string &getVideoUrl() const {
        return videoUrl;
    }

    void setVideoUrl(const string &videoUrl) {
        Restaurant::videoUrl = videoUrl;
    }

    const vector<FoodItem> &getItems() const {
        return items;
    }

    void setItems(const vector<FoodItem> &items) {
        Restaurant::items = items;
    }

    void addItems(const FoodItem &item) {
        this->items.push_back(item);
    }

    string gen_random(const int len) {
        string tmp_s;
        static const char alphanum[] =
                "0123456789"
                "ABCDEFGHIJKLMNOPQRSTUVWXYZ"
                "abcdefghijklmnopqrstuvwxyz";
        srand( (unsigned) time(NULL) * getpid());
        tmp_s.reserve(len);
        for (int i = 0; i < len; ++i)
            tmp_s += alphanum[rand() % (sizeof(alphanum) - 1)];
        return tmp_s;

    }

    const string &getId() const {
        return id;
    }

    void printItems() {
        for(auto it: items) {
            cout<<"item: "<<it.getName()<<endl;
        }
    }


private:
    string id;
    string name;
    string description;
    double lat;
    double lang;
    string imageUrl;
    string videoUrl;
    string createdAt;
    string updatedAt;
    vector<FoodItem> items;
};

Restaurant.h

#include <bits/stdc++.h>
#include <vector>
#include "FoodItem.h"

using namespace std;

class Restaurant {
public:

    Restaurant() {
        this->id = gen_random(12);
    }

    virtual ~Restaurant() {

    }

    const string &getName() const {
        return name;
    }

    void setName(const string &name) {
        Restaurant::name = name;
    }

    const string &getDescription() const {
        return description;
    }

    void setDescription(const string &description) {
        Restaurant::description = description;
    }

    double getLat() const {
        return lat;
    }

    void setLat(double lat) {
        Restaurant::lat = lat;
    }

    double getLang() const {
        return lang;
    }

    void setLang(double lang) {
        Restaurant::lang = lang;
    }

    const string &getImageUrl() const {
        return imageUrl;
    }

    void setImageUrl(const string &imageUrl) {
        Restaurant::imageUrl = imageUrl;
    }

    const string &getVideoUrl() const {
        return videoUrl;
    }

    void setVideoUrl(const string &videoUrl) {
        Restaurant::videoUrl = videoUrl;
    }

    const vector<FoodItem> &getItems() const {
        return items;
    }

    void setItems(const vector<FoodItem> &items) {
        Restaurant::items = items;
    }

    void addItems(const FoodItem &item) {
        this->items.push_back(item);
    }

    string gen_random(const int len) {
        string tmp_s;
        static const char alphanum[] =
                "0123456789"
                "ABCDEFGHIJKLMNOPQRSTUVWXYZ"
                "abcdefghijklmnopqrstuvwxyz";
        srand( (unsigned) time(NULL) * getpid());
        tmp_s.reserve(len);
        for (int i = 0; i < len; ++i)
            tmp_s += alphanum[rand() % (sizeof(alphanum) - 1)];
        return tmp_s;

    }

    const string &getId() const {
        return id;
    }

    void printItems() {
        for(auto it: items) {
            cout<<"item: "<<it.getName()<<endl;
        }
    }


private:
    string id;
    string name;
    string description;
    double lat;
    double lang;
    string imageUrl;
    string videoUrl;
    string createdAt;
    string updatedAt;
    vector<FoodItem> items;
};
Remy Lebeau
  • 555,201
  • 31
  • 458
  • 770
Mrugesh
  • 4,381
  • 8
  • 42
  • 84
  • the list is empty? – OznOg Mar 27 '21 at 17:41
  • Have you tried using a debugger? Please provide a [mre] (with a focus on minimal) and explain what your code is supposed to do – Alan Birtles Mar 27 '21 at 17:44
  • yes, @OznOg debugged the code FoodItem list inside Restaurant is empty when I am getting it via MenuCreator file – Mrugesh Mar 27 '21 at 17:52
  • There's quite a bit of room for improvement in your code. [Don't `#include `](https://stackoverflow.com/questions/31816095/why-should-i-not-include-bits-stdc-h), unnecessary use of `this->`, `lang` should be `longitude`, [avoid `std::endl`](https://stackoverflow.com/questions/213907/stdendl-vs-n), in `gen_random()` you should call `resize()` instead of `reserve()`, and so on. Once you get a working program, consider posting it on [Code Review](https://codereview.stackexchange.com/). – G. Sliepen Mar 27 '21 at 18:37
  • 2
    In `createMenu`, you call `c1.addRestaurants` after `m1.addCategory(c1)`. The copy of `c1` stored in `m1` doesn't have any restaurants in it. – Igor Tandetnik Mar 28 '21 at 00:32

1 Answers1

1

When createMenu() in main.cpp is setting up the menu, it creates a local Category object named c1 and adds it to the menu, which makes a copy of c1 when pushingnit into the MenuCreator::categories vector. No Restaurant objects had been added to c1 yet when that copy is created. So when a Restaurant is then added to c1 afterwards, the copy is not updated. That is why there are no Restaurant objects in the menu when MenuCreator::getRestaurantsForCategory() tries to return them.

Change createMenu() to fully initialize c1 before adding it to the menu, eg:

void createMenu() {
    m1.createMenu("sg");
    Category c1;
    c1.setName("Non-veg");
    Restaurant r1;
    r1.setName("ABC");
    r1.setDescription("Test Restaurant");
    createRestaurantItem(r1);
    c1.addRestaurants(r1);
    m1.addCategory(c1); // <-- move down here
}

Also, on a side note, the return value of MenuCreator::getRestaurantsForCategories() is undefined if the specified category is not found. Since the return value is a reference to a vector, it needs to either return a static vector that is empty, or else throw an exception.

Remy Lebeau
  • 555,201
  • 31
  • 458
  • 770
  • is there any way to pass it by reference so that I don't have to maintain the order in which it was added? – Mrugesh Mar 28 '21 at 18:24
  • @MrugeshThaker you can't store references in `std::vector` (unless you use `std::reference_wrapper`, but you risk dangling references when objects go out of scope). You can store pointers, which means using dynamic allocations with `new`/`std::unique_ptr`. Otherwise, you may need a redesign. For instance, have `MenuCreator::addCategory()`, `MenuCreator::addRestaurantForCategory()`, `Category::addRestaurants()`, `Restaurant::addItems()`, etc not take an object as input, but instead create and store an object internally, and then return a reference to it for the caller to fill in as needed. – Remy Lebeau Mar 28 '21 at 18:34