为我不恰当的术语道歉。
如果条目不存在,我有一段代码返回NULL指针:
ObjectType * MyClass::FindObjectType( const char * objectTypeName )
{
if ( objectTypeMap.find( objectTypeName ) == objectTypeMap.end() )
{
Msg( "\n[C++ ERROR] No object type: %s", objectTypeName );
return NULL;
}
else
return &objectTypeMap[ objectTypeName ];
}
我想做同样的事情,但这次返回一个对象而不是一个指针。以下代码没有给我任何编译器错误(这让我感到惊讶):
ObjectType MyClass::FindObjectType( const char * objectTypeName )
{
if ( objectTypeMap.find( objectTypeName ) == objectTypeMap.end() )
{
Msg( "\n[C++ ERROR] No object type: %s", objectTypeName );
}
else
return objectTypeMap[ objectTypeName ];
}
使用指针,我可以检查是否找不到条目:
if ( FindObjectType( objectType ) == NULL )
//Do something
如何对返回的对象执行等效检查?
答案 0 :(得分:12)
对象没有语言级别的等价物。
一个选项是创建一个“sentinel”对象,保证比较不等于任何“真实”对象,并返回:
class ObjectType {
public:
static const ObjectType null;
bool operator==(const ObjectType &rhs) const { /* need an appropriate comparison test */ }
...
};
ObjectType ObjectType::null(/* something unique */);
...
ObjectType foo(const char *objectTypeName) {
if (cond) {
return objectTypeMap[objectTypeName];
} else {
return ObjectType::null;
}
}
...
if (foo(objectType) == ObjectType::null) {
std::cout << "Returned the null object\n";
}
答案 1 :(得分:4)
以下代码未给出错误,因为标准非常保守。
某些代码结构非常复杂,编译器无法知道是否可以到达函数的结尾。因此标准说,编译器不必证明函数正确返回值...
然而标准确实说如果函数正常结束(没有异常)而没有返回值,则调用未定义行为(即,任何事情都可能发生,可能是崩溃)。因此,对于这种情况,大多数编译器都有警告,对于gcc和Clang,您可以使用-Wreturn
。
现在,nullity或 sentinel values 的原则并不新鲜,而且空指针只是一个化身(在众多中)。
如果你的对象没有意义可以为空(它很少但可能是权宜之计)那么你有两种选择:
throw
表示错误的异常boost::optional<ObjectType>
)在这种情况下,由于预计Find
可能找不到任何东西,我会建议后者。
用法很简单:
boost::optional<ObjectType> MyClass::FindObjectType(char const* objectTypeName )
{
if ( objectTypeMap.find( objectTypeName ) == objectTypeMap.end() ) {
// do not print anything, it is up to the caller to decide what to do
return boost::none;
}
return objectTypeMap[ objectTypeName ];
}
然后来电者写道:
int main(int argc, char* argv[]) {
if (boost::optional<ObjectType> o = MyClass::FindObject(argv[1])) {
o->foo();
return 0;
}
Msg( "\n[C++ ERROR] No object type: %s", argv[1]);
return 1;
}
答案 2 :(得分:2)
C ++ 17引入了std::optional
作为标准库的一部分,它是该语言中最接近空对象的东西,类似于其他编程语言中的“ Maybe”。它的工作原理很像the previous answer中所述的boost::optional
。打算解决的用例之一是从函数返回可选值。
#include <iostream>
#include <optional> // Defines std::optional
std::optional<int> f(bool test) {
if (test) {
return 1;
} else {
return std::optional<int>();
}
}
int main()
{
auto ret = f(true);
// std::optional can be used as a bool
if (ret) {
std::cout << "Value for first test: " << ret.value() << '\n';
} else {
std::cout << "Value for first test: " << 0 << '\n';
}
std::cout << "Value for second test: " << (f(true)).value_or(0) << '\n';
std::cout << "Value for third test: " << (f(false)).value_or(0) << '\n';
return 0;
}
输出:
Value for first test: 1
Value for second test: 1
Value for third test: 0