开发者

When returning a pointer, what to return if it's not found? C++

开发者 https://www.devze.com 2022-12-11 08:28 出处:网络
I\'m not sure what to return as a default? myDrugs is a private vector<Drug*> container Drug* DrugDealer::getFirstDrugInSack(DrugType drugtobuy开发者_Python百科)

I'm not sure what to return as a default?

myDrugs is a private vector<Drug*> container

Drug* DrugDealer::getFirstDrugInSack(DrugType drugtobuy开发者_Python百科)
{
    for (int i = 0; i < myDrugs.size(); i++)
    {
        if (myDrugs[i]->getType() == drugtobuy)
            return myDrugs[i];
    }

    return 0; // is this right?
}

So I would call it like:

Drug *d = DrugDealer->getFirstDrugInSack(DrugType::Weed);
if (d != 0)
    // do something
else
    // onose?

Or is there a better way to do this?


I would say it depends on whether the function expects to find the value, and this comes down to how well-defined and cohesive your function is, and what type of contract it is providing to client code.

If it is acceptable to not find the value, I would say that returning a NULL pointer in this case is valid as a way of indicating to the client code that the value couldn't be found.

If it is an exceptional circumstance to not find a value and this indicates that there is something wrong, perhaps one of the following approaches is better:

  • Throwing an exception.
  • Asserting in conjunction with returning NULL. Asserting on its own is usually not recommended as these are (usually) compiled out of Release builds.

In your case I would say that returning NULL is acceptable, but as indicated above this changes for every situation and there is no particular "rule of thumb" to apply here.


Some people prefer NULL to 0. You could also raise an exception.


Returning NULL is Ok. You may also consider passing a pointer to pointer as a parameter and returning boolean value, true if it is found and false if it is not:

bool DrugDealer::getFirstDrugInSack(DrugType drugtobuy, Drug** out)
{
    for (int i = 0; i < myDrugs.size(); i++)
    {
        if (myDrugs[i]->getType() == drugtobuy) {
           *out = myDrugs[i];
           return true;
        }

    }

    return false;
}

Calling:

Drug* d;
if (dealer->getFirstDrugInSack(dragType, &d)) {
  // Found it, use it
}


Drug *myDrug = NULL;
In the loop, myDrug = myDrugs[i] followed by break;
and return myDrug.


I would say you have three options:

  1. return 0
  2. throw an exception
  3. use the Null object pattern

1) Has the drawback that you have to test for 0 if you want to avoid exceptions. This is not the way to go if you write modern C++ code as it makes the code jumpy (a lot of if's) and exceptions would make the code slow if the case where 0 is returned in not that likely (then it is not really an exception ;-) )

2) Same thing, only a way to go if the situation is unlikely

3) This will make the code work in all cases, only where you have to check if there are drugs or not, you have to compare to the defined NullObject, not to 0. This could alternatively also be solved by using std::shared_ptr (which has become part of the new C++ standard lib, if you have an older STL, you can use boost::shared_ptr, it is a header only template class)

FYI: I gathered the design patterns I could find and put them into an overviewable list http://www.color-of-code.de/index.php?option=com_content&view=article&id=68:software-patterns&catid=43:design&Itemid=66 There are backlinks to wikipedia for the entries I could find.

EDIT: Here the link for the Null Object Pattern only: http://en.wikipedia.org/wiki/Null_Object_pattern


Yes, this is OK. Consider using exceptions if the case where you don't have an object doesn't occur too often, and the code handling those objects gets complex.


another option you can make use of is returning a NullObject

return Drug::NullDrug;

basically a valid drug object that is considered "NUll" means that if you use it, it won't break.

though generally I'd go with returning 0;

well,

usually, I'd be using smart ptrs.

0

精彩评论

暂无评论...
验证码 换一张
取 消