given the header file and cpp file below is there any fucntions or method that can be logically improved?
class MyDataStore: public DataStore{
public:
    MyDataStore();
    void addProduct(Product* p);
    void addUser(User* u);
    std::vector<Product*> search(std::vector<std::string>& terms, int type);
    void dump(std::ostream& ofile);
    
    void add (std::string user, Product* p);
    void buy (std::string user);
    void view (std::string user);
    
    
private:
    std::vector<Product*> hits;
    std::map<std::string, std::set<Product*>> m_keywords;
    std::map<std::string, User*> users;
    std::map<std::string, std::vector<Product*>> carts;
    std::vector<Product*> allproducts;
    std::vector<User*> allusers;
};

MyDataStore::MyDataStore()
{
}

void MyDataStore::addProduct(Product* p)
{
    allproducts.push_back(p);
    
    set<string> kwords = p -> keywords();
    set<string>::iterator it;

      for (it = kwords.begin();
           it != kwords.end(); it++)
      {
        m_keywords[*it].insert(p);
      }
}


void MyDataStore::addUser(User* u)
{
    allusers.push_back(u);
    users[u->getName()] = u;
}


std::vector<Product*> MyDataStore::search(std::vector<std::string>& terms, int type)
{
    set<Product*> temp;
    if (type == 0 && !terms.empty()){
        temp = m_keywords[terms[0]];
        for (size_t i = 1; i < terms.size(); i++){
            temp = setIntersection(temp, m_keywords[terms[i]]);
        }
    }

    else if (type == 1 && !terms.empty()){
        temp = m_keywords[terms[0]];

        for (size_t i = 1; i < terms.size(); i++){
            temp = setUnion(temp, m_keywords[terms[i]]);
        }
    }
    
    else{
        cout << "Invalid request" << endl;
        vector<Product*> empty;
        return empty;
    }

    vector<Product*> ret_vec(temp.begin(), temp.end());
    return ret_vec;
}

void MyDataStore::add(string user, Product* p)
{
    if (users.find(user) != users.end()){
        carts[user].push_back(p);
    }   else{
        cout << "invalid username" << endl;
    }
}

void MyDataStore::buy(string user){
    if (users.find(user) != users.end()){
        for (unsigned i=0; i<carts[user].size();i++){
            double amount = carts[user][i] -> getPrice();
            double balance = users[user] -> getBalance();
            int quantity = carts[user][i] -> getQty();
            
            if (balance >= amount && quantity > 0){
                carts[user][i] -> subtractQty(1);
                users[user] -> deductAmount(amount);
                carts[user].erase(carts[user].begin()+i);
                i--;
            }          
        }
        
    }
    else {
        cout << "Invalid username" << endl;
    }
}

void MyDataStore::view(string user)
{   
  if(users.find(user) != users.end())
  {
    vector<Product*>::iterator it;
    int index = 1;
    for(it = carts[user].begin(); it != carts[user].end(); it++)
    {
      cout << "Item " << index << endl;
      cout << (*it)->displayString() << endl; // displays the string
        index++;
    }
  } else {
      cout << "Invalid username" << endl;
  }
}

void MyDataStore::dump(std::ostream& ofile)
{
  ofile << "<products>" << endl;
  for (std::size_t i = 0; i < allproducts.size(); ++i)
  {
    allproducts[i] -> dump(ofile);
  }
  ofile << "</products>" << endl;
  ofile << "<users>" << endl;
  for (std::size_t i = 0; i < allusers.size(); ++i)
  {
    allusers[i] -> dump(ofile);
  }
  ofile << "</users>" << endl;
}