-1

I have a class

class MyClass {
   public:
     string name;
};

I have a class manager, with a vector of said classes.

class MyManager { 
 public:
   vector<MyClass> classes;
};

I want to pull out a class from the vector by looping and matching with the name

int MyManager::FindMyClass(string name, MyClass *clazz){
    vector<MyClass>::iterator it;
    for(it = classes.begin(); it != classes.end(); ++it){
        if(it->name == name){
            // if i cout here, i see the cout, so i did find it..
            *clazz = *it;
            return 1;
        }
    }
    return 0;
}

int main() {
    MyClass *myClass;
    int result = myManager.FindMyClass("bob", *myClass);
}

I know for a fact that the object is matched properly (see the comment). I've tried every combination of pointers, double pointers, references, and get every error from unknown conversions to invalid pointers. I am just not sure what I have to do to get a reference to the class stored in the vector.

J Doe.
  • 299
  • 3
  • 13
  • `myManager.FindMyClass("bob", *myClass);` is a type error. `*myClass` is a `MyClass`, not a `MyClass *`. If it weren't a type error, it would have undefined behavior: You're trying to read from an uninitialized variable. – melpomene Oct 26 '17 at 21:15

1 Answers1

2

Change the argument type to MyClass*& so you can return a pointer to the object found in the vector.

int MyManager::FindMyClass(string name, MyClass* &foundPointer)

MyClass *myClass;
int result = myManager.FindMyClass("bob", myClass);

Once you find the match, you can get a pointer to the object using

foundPointer = &(*it);

I would also recommend changing the return type to bool.

Here's an updated version of the function:

bool MyManager::FindMyClass(string name, MyClass* &foundPointer)
{
   vector<MyClass>::iterator it = classes.begin();
   for(; it != classes.end(); ++it)
   {
      if(it->name == name)
      {
         foundPointer = &(*it);
         return true;
      }
   }
   return false;
}

Suggested second improvement:

Change the return type to MyClass*. Return a pointer to the found object or nullptr if none is found.

MyClass* MyManager::FindMyClass(string name)
{
   ...
}

Suggested third improvement:

Use the standard library function std::find_if and a lambda expression to simplify your function.

auto it = std::find_if(classes.begin(),
                       classes.end(),
                       [&](const MyClass &c) { return (c.name == name); });

The updated function:

MyClass* MyManager::FindMyClass(string name)
{
   auto it = std::find_if(classes.begin(),
                          classes.end(),
                          [&](const MyClass &c) { return (c.name == name); });
   if ( it != classes.end() )
   {
      return &(*it);
   }
   return nullptr;
}
R Sahu
  • 204,454
  • 14
  • 159
  • 270
  • Thank you. This works perfectly. Would you be able to explain it a bit more.. I am struggling very hard with pointers and just don't understand what is going on with `MyClass*&` as well as `foundPointer = &(*it)` – J Doe. Oct 26 '17 at 21:19
  • 2
    @JDoe., those are fundamental aspects of the language. You will be better off picking a text book and reading through it to understand the basics. Here's a [starting point](http://stackoverflow.com/questions/388242/the-definitive-c-book-guide-and-list). – R Sahu Oct 26 '17 at 21:21
  • 1
    Instead of using an output parameter, I would `return &(*it);` the matching object, and `return nullptr;` if no match is found: `MyClass *myClass = myManager.FindMyClass("bob");` And consider using `std::find_if()` instead of a manual loop: `auto it = std::find_if(classes.begin(), classes.end(), [&](const MyClass &c) { return (c.name == name); });` – Remy Lebeau Oct 26 '17 at 22:39
  • Thanks but I should have specified im stuck pre-c++ 11, i think c++ 98 – J Doe. Oct 27 '17 at 13:46