C++ 如何在C++中返回NULL对象
声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow
原文地址: http://stackoverflow.com/questions/7425241/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me):
StackOverFlow
How to return NULL object in C++
提问by Hymanie Ortiz
I know that this might be a duplicate of: Return a "NULL" object if search result not found
我知道这可能是以下内容的重复:如果未找到搜索结果,则返回“NULL”对象
BUT, there's something different going on with my code because the asterisk doesn't solve my problem, which is this:
但是,我的代码有些不同,因为星号不能解决我的问题,这是:
Normal Sphere::hit(Ray ray) {
//stuff is done here
if(something happens) {
return NULL;
}
//other stuff
return Normal(something, somethingElse);
}
But I get an error referencing the return NULL
line: conversion from ‘int' to non-scalar type ‘Normal' requested
但是我在引用该return NULL
行时出现错误:conversion from ‘int' to non-scalar type ‘Normal' requested
And another error and warning that referencing the last return line: warning: taking address of temporary
and conversion from ‘Normal*' to non-scalar type 'Normal' requested
另一个错误和警告引用了最后一个返回行:warning: taking address of temporary
和conversion from ‘Normal*' to non-scalar type 'Normal' requested
I understand why I am getting this warning, but I don't know how to fix it. How do I return a Normal
object in the last line that persists after the function ends and how do I return a NULL
object that first time? (If there's a term for these types of returns, please let me know so I can also read up on it more.)
我明白为什么会收到此警告,但我不知道如何解决。如何Normal
在函数结束后仍然存在的最后一行中返回一个NULL
对象,以及如何第一次返回一个对象?(如果有这些类型的退货的术语,请告诉我,以便我也可以详细阅读。)
To clarify a commenter's question, I've tried these things:
为了澄清评论者的问题,我尝试了以下方法:
I tried doing this: Normal *Sphere::hit(Ray ray)
in the cpp file and Normal *hit( Ray ray );
in the header file and I get this error: error: prototype for ‘Normal* Sphere::hit(Ray)' does not match any in class 'Sphere'
我尝试这样做:Normal *Sphere::hit(Ray ray)
在 cpp 文件和Normal *hit( Ray ray );
头文件中,我收到此错误:error: prototype for ‘Normal* Sphere::hit(Ray)' does not match any in class 'Sphere'
I also tried this: Normal Sphere::*hit(Ray ray)
in the cpp file and Normal *hit( Ray ray);
in the header file and I get this error for the second return statement: cannot convert 'Normal*' to 'Normal Sphere::*' in return
我也试过这个:Normal Sphere::*hit(Ray ray)
在cpp文件和Normal *hit( Ray ray);
头文件中,第二个返回语句出现这个错误:cannot convert 'Normal*' to 'Normal Sphere::*' in return
Further clarification:I'm not asking about how pointers work. (That wasn't the main question.) I'm wondering about syntax regarding pointers in C++. So, given the function I've specified above, I've gleaned that I should specify a return a pointer because C++ doesn't have null objects. Got it. BUT, the problem then becomes: what should the function prototype look like? In the cpp file, I have what Bala suggested (which is what I had originally but changed it because of the following error):
进一步说明:我不是在问指针是如何工作的。(那不是主要问题。)我想知道有关 C++ 中指针的语法。因此,鉴于我在上面指定的函数,我发现我应该指定一个返回指针,因为 C++ 没有空对象。知道了。但是,问题就变成了:函数原型应该是什么样的?在 cpp 文件中,我有 Bala 建议的内容(这是我最初的内容,但由于以下错误而对其进行了更改):
Normal* Sphere::hit(Ray ray) {
//stuff is done here
if(something happens) {
return NULL;
}
//other stuff
return new Normal(something, somethingElse);
}
In the header file, I have Normal *hit(Ray ray)
, but I still get this message: prototype for 'Normal* Sphere::hit(Ray)' does not match any in class 'Sphere'
At this point, it is unclear to me why it can't find that function prototype. Here is the header file:
在头文件中,我有Normal *hit(Ray ray)
,但我仍然收到此消息:prototype for 'Normal* Sphere::hit(Ray)' does not match any in class 'Sphere'
此时,我不清楚为什么找不到该函数原型。这是头文件:
class Sphere
{
public:
Sphere();
Vector3 center;
float radius;
Normal* hit(Ray ray);
};
Can anyone see why it's complaining that there doesn't exist a matching prototype for hit
in the Sphere
class? (I might move this to a separate question...)
任何人都可以看到它为什么抱怨不存在匹配原型hit
的Sphere
类?(我可能会将其移至一个单独的问题...)
回答by Michael Anderson
There are several fairly standard ways of doing this. There are different tradeoffs for the methods, which I'm not going to go into here.
有几种相当标准的方法可以做到这一点。这些方法有不同的权衡,我不打算在这里讨论。
Method 1: Throw an exception on failure.
方法一:失败时抛出异常。
Normal Sphere::hit(Ray ray)
{
//stuff is done here
if(something happens) {
throw InvalidIntersection;
}
//other stuff
return Normal(something, somethingElse);
}
void example(Ray r)
{
try {
Normal n = s.hit(r);
... SUCCESS CASE ...
}
catch( InvalidIntersection& )
{
... FAILURE CASE ...
}
}
Method 2 return a pointer to a newly allocated object. (You could also use smart pointers, or auto_ptrs to make this a little neater).
方法 2 返回一个指向新分配对象的指针。(您也可以使用智能指针或 auto_ptrs 使其更简洁)。
Normal* Sphere::hit(Ray ray)
{
//stuff is done here
if(something happens) {
return NULL
}
//other stuff
return new Normal(something, somethingElse);
}
void example(Ray ray)
{
Normal * n = s.hit(ray);
if(!n) {
... FAILURE CASE ...
} else {
... SUCCESS CASE ...
delete n;
}
}
Method 3 is to update an existing object. (You could pass a reference, but a convention I use is that any output parameter is passed by pointer).
方法 3 是更新现有对象。(您可以传递引用,但我使用的约定是任何输出参数都通过指针传递)。
bool Sphere::hit(Ray ray, Normal* n)
{
//stuff is done here
if(something happens) {
return false
}
//other stuff
if(n) *n = Normal(something, somethingElse);
return true;
}
void example(Ray ray)
{
Normal n;
if( s.hit(ray, &n) ) {
... SUCCESS CASE ...
} else {
... FAILURE CASE ...
}
}
Method 4: Return an optional<Normal>
(using boost or similar)
方法 4:返回一个optional<Normal>
(使用 boost 或类似方法)
optional<Normal> Sphere::hit(Ray ray)
{
//stuff is done here
if(something happens) {
return optional<Normal>();
}
//other stuff
return optional<Normal>(Normal(something, somethingElse));
}
void example(Ray ray)
{
optional<Normal> n = s.hit(ray);
if( n ) {
... SUCCESS CASE (use *n)...
} else {
... FAILURE CASE ...
}
}
回答by Bala R
I think you need something like
我认为你需要类似的东西
Normal* Sphere::hit(Ray ray) {
//stuff is done here
if(something happens) {
return NULL;
}
//other stuff
return new Normal(something, somethingElse);
}
to be able to return NULL;
能够返回NULL;
回答by Johan R?de
If you use the Boost libraries, then you can use boost::optional. That gives you something that is pretty close to a null value:
如果您使用 Boost 库,那么您可以使用 boost::optional。这为您提供了非常接近空值的东西:
boost::optional<Normal> Sphere::hit(Ray ray) {
//stuff is done here
if(something happens) {
return boost::none;
}
//other stuff
return Normal(something, somethingElse);
}
boost::optional< T> is a wrapper class that contains either an instance of T or boost::none (an instance of boost::none_t).
boost::optional< T> 是一个包装类,它包含 T 的实例或 boost::none(boost::none_t 的实例)。
See http://www.boost.org/doc/libs/1_47_0/libs/optional/doc/html/index.htmlfor more details.
有关更多详细信息,请参阅http://www.boost.org/doc/libs/1_47_0/libs/optional/doc/html/index.html。
回答by seand
In C++ there's no such thing as a "null object". There are null pointers though. You can implement a special object of your design that you logically treat as "null" but it's not part of the C++ language.
在 C++ 中,没有“空对象”这样的东西。虽然有空指针。您可以实现设计的一个特殊对象,在逻辑上将其视为“空”,但它不是 C++ 语言的一部分。
回答by Miguel
The NULL return value would only be valid if you were returning a pointer to a Normal object, NULL represents a null pointer, not a null object.
NULL 返回值只有在您返回一个指向 Normal 对象的指针时才有效,NULL 代表一个空指针,而不是一个空对象。
What I would do in this case is define a 'null' or invalid state for this object. Since you are working with surface normals, you can consider a normal with length == 0 an invalid state, so then you would do this:
在这种情况下,我要做的是为此对象定义一个“空”或无效状态。由于您正在使用表面法线,您可以将长度 == 0 的法线视为无效状态,因此您可以这样做:
Normal Sphere::hit(Ray ray) {
//stuff is done here
if(something happens) {
return Normal();
}
//other stuff
return Normal(something, somethingElse);
}
Then your normal class would have something like this:
那么你的普通班级会有这样的事情:
class Normal {
public:
Normal() : x(0), y(0), z(0), len(0) {}
// ... other constructors here ...
bool isValid() const { return (len != 0) };
// ... other methods here ...
private:
float x, y, z, len;
};
回答by Shailav
You shouldn't return NULL
, which is a zero constant of type int
, but instead, return an empty instance of class Normal
constructed by the no arg constructor, usually.
您不应该 return NULL
,它是 type 的零常量int
,而是Normal
通常返回由 no arg 构造函数构造的类的空实例。
So return Normal();
所以返回 Normal();
Generally, it is good practice to additionally have the method isEmpty()
defined.
通常,另外isEmpty()
定义方法是一种很好的做法。
That way you could check for a Null
instance like so:
这样你就可以Null
像这样检查一个实例:
if(obj_of_class_Normal.isEmpty())
//do something.
回答by sashang
BUT, there's something different going on with my code because the asterisk doesn't solve my problem, which is this:
但是,我的代码有些不同,因为星号不能解决我的问题,这是:
It seems that from your question you expect that simply adding a *
after the class name will solve your problems. However this sort of expectation comes from a lack of understanding what a pointer is, when to use pointers and the importance of the type system. So the remainder of this answer will hopefully clarify these points.
从您的问题来看,您似乎希望*
在类名后简单地添加一个就可以解决您的问题。然而,这种期望来自于对指针是什么、何时使用指针以及类型系统的重要性缺乏了解。因此,本答案的其余部分有望澄清这些要点。
Firstly the C++ is a strongly typed lanuage. This means that when assigning one variable to another that 2 variables in question have to be of the same type. For example assume that in the code below A and B are basic classes with no members defined:
首先,C++ 是一种强类型语言。这意味着当将一个变量分配给另一个变量时,有问题的 2 个变量必须是相同的类型。例如假设在下面的代码中 A 和 B 是没有定义成员的基本类:
A a;
B b;
a = b; //compiler error here due to type mismatch
This is because a
and b
are different types.
这是因为a
和b
是不同的类型。
Now say you created a pointer by using the *
. This is also a different type of variable:
现在假设您使用*
. 这也是一种不同类型的变量:
A a;
A* p_a;
a = p_a; //compiler error due to type mismatch
p_a
is not the same type of variable as a
.
p_a
与 的变量类型不同a
。
Now the error:
现在错误:
conversion from ‘int' to non-scalar type ‘Normal' requested
请求从“int”到非标量类型“Normal”的转换
is generated because the expression:
生成是因为表达式:
return NULL
is of type int
(you'll find if you look it up it's #defined as 0) but the return type of your function is Normal
.
是类型int
(如果您查找它,您会发现它的 #defined 为 0)但您的函数的返回类型是Normal
.
To resolve this you have to change the function return type to be a pointer to a Normal
object.
要解决此问题,您必须将函数返回类型更改为pointer to a Normal
对象。
Normal* Sphere::hit(Ray ray)
and return a pointer to a Normal
object:
并返回一个pointer to a Normal
对象:
return new Normal(something, somethingElse);
However at this stage although compiler errors should be resolved, you now have the concern of managing the dynamically allocated memory. I can't cover that in this post so I'll leave it like it is.
然而,在这个阶段,虽然编译器错误应该得到解决,但您现在需要关注管理动态分配的内存。我无法在这篇文章中介绍它,所以我会保持原样。
Update:
更新:
This is to address the 2nd part in your question. Your class declaration in your header file should be terminated with a ;
.
这是为了解决您问题中的第二部分。头文件中的类声明应该以;
.