- Java 双重比较
- java - 比较器与 Apache BeanComparator
- Objective-C 完成 block 导致额外的方法调用?
- database - RESTful URI 是否应该公开数据库主键?
做这样的事情不好吗? (在使用对象指针进行操作之前不检查 draw() 函数内的 nullptr)
class SomeClass
{
public:
SomeClass(Object& someValidObject)
{
object = &someValidObject;
}
void draw()
{
object->draw();
}
Object* object = nullptr;
}
或者我是否应该在调用对象中的操作之前始终检查 nullptr,即使构造函数肯定会使指针指向某物?
void draw()
{
if(object != nullptr)
object->draw?
}
最佳答案
取决于您要防范什么。
正如指出的那样in the comments已经,您无法可靠地检查悬挂指针,因此如果传递的 Object
在您的 SomeClass
之前超出范围,就会发生不好的事情。
因此,您唯一可以可靠地检查的是指针是否为 nullptr
,但正如您自己注意到的那样,目前构造函数几乎不可能做到这一点。但是,只要您的 object
成员变量像现在这样是 public
,理论上用户可以到达那里并将其设置为 nullptr
.您可以通过使成员 private
并使用拒绝 nullptr
值的 setter(或简单地采用引用,如构造函数)来使其变得更难。在这样的设计中,object != nullptr
可以被认为是一个class invariant,这是一个在每个成员函数调用前后都为真的条件(从构造后的时间开始)直到销毁之前)。
那么我们如何打破类不变量呢?作为客户,我们可以违反函数的先决条件,从而使类进入未定义状态。对于像您的示例一样简单的类,这很难做到,因为函数实际上没有先决条件。但是,为了争论起见,我们假设您要添加这样的 setter:
// Precondition: obj must point to a valid Object.
// That object must be kept alive for the lifetime of the class,
// otherwise the behavior is undefined.
void setObject(Object* obj)
{
object = obj;
}
现在这有点微妙。代码允许我们在此处传递一个 nullptr
,但文档明确禁止这样做。如果我们传递一个 nullptr
或让传递的对象在我们的 SomeClass
之前消亡,我们就违反了该类的约定。但是这个契约并没有在代码中强制执行,它只在注释中。
这里要认识到的重要一点是,有些情况无法在代码中检查。我们可以检查 nullptr
,但不能检查悬挂指针。有时检查是可能的,但由于运行时成本高而不受欢迎(例如,检查一个范围是否已排序以进行二分查找)。一旦我们意识到这一点,很明显我们作为类设计者在这里有一些回旋余地。既然我们无论如何都不能使事情 100% 防弹,我们是否应该检查任何东西?当然,我们可以在任何地方检查 nullptr
,但这意味着要付出运行时开销来检查基本上是编程错误的内容。
如果我不想在生产构建中支付这笔开销怎么办?如果我在开发过程中犯了错误,我可能希望我的调试器能够捕捉到它,但我不希望我的客户必须在发布后支付检查费用。
所以你真正要找的是断言:
void draw()
{
assert(object);
object->draw();
}
决定是检查断言中的某些内容(或根本不检查)还是进行适当的运行时检查(作为契约(Contract)的一部分)并不是一件容易的事情。这往往是一个哲学问题。 John Lakos 给出了出色的 talk about this at CppCon 2014如果您想深入挖掘。
关于c++ - 我是否应该始终检查 nullptr 的成员指针?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/39715484/
test = (function(){var key = 200; return {getKey : function(){return key} }; })(); test.
如果这个问题可能一直被问到,我很抱歉,但我进行了搜索,但找不到足够的答案。 如果公共(public)成员/方法正在访问私有(private)成员/字段,如何禁用它们的继承? 所以考虑一下: publi
重要的澄清:一些评论者似乎认为我是从 union 复制的。仔细查看 memcpy,它从一个普通的旧 uint32_t 地址复制而来,该地址不包含在 union 中。另外,我正在(通过 memcpy)复
spinner 通常只显示一个字符串,在我想分配 IDpersonne 和 Name 的情况下,旋转器必须告诉我名字。当我得到选定的项目时,我必须得到 ID。我该怎么做? 最佳答案 我假设您已将项目排
A 类的实例是 B 类的公共(public)成员。B 类的实例也是 A 的公共(public)成员。在什么情况下可能需要这种实现?我的意思是是否有一个或多个标准场景需要这种实现方式?更具体的细节:我有
我如何设置我的 web.config 以使用表单例份验证,将成员身份提供程序设置为 ActiveDirectoryMembershipProvider 并使用内置登录控件。这样我就可以使用有效的事件目
这个问题已经有答案了: Should methods in a Java interface be declared with or without a public access modifier?
因此根据定义,类中的私有(private)数字在序列化时以类名作为前缀。这对我来说是一个问题,我希望能够序列化/保存/反序列化一个确切的对象,但是 php 所做的是给我另一个 classname+va
我实现了一个成员? clojure 中的函数如下: (defn member? [item seq] (cond (empty? seq) false (= item (first
我在这里的问题似乎总是与使用函数有关。它仍然让我困惑!在本教科书练习中,我被要求按值传递结构,然后调整它并按引用传递。最初我设计的代码是在 main 中完成所有工作。现在我正在传递值。所以我添加了新函
所以我有这些变量 List files, images = new List(); string rootStr; 还有这个线程函数 private static int[] thread_searc
我对 C++ 模板和尝试弄清楚部分模板特化还比较陌生。我正在使用模板实现几个相关的数据结构:用于概率存在/不存在查询的布隆过滤器(基于位数组),以及用于丰度查询的计数布隆过滤器(带有整数数组)。我从以
例如在 java 中,我在外部类和内部类中声明并初始化了一个 JButton,我决定在某些情况下将其隐藏,这是一种安全的编程实践吗? 最佳答案 内部类的全部目的是它们可以访问到环绕内部类的外部类。 所
我有一个使用库进行通信的类: class Topic { Topic( Type T, String name ); }; class Reader { Reader (Topic, Stri
我在两个单独的文件中有以下代码。 package animal; public class Frog { protected void ribbit() { Syste
我有一个分数列表。使用这些,我需要从 redis 排序集中提取值。 我知道我可以使用 zrangebyscore - 但如果我提供的列表中的分数不连续怎么办?在这种情况下,我不能依赖 zrangeby
过去几年我一直被 C# 编码宠坏了,现在我又回到了 C++ 并发现我在处理本应很简单的东西时遇到了麻烦。我正在为 gamedev 使用名为 DarkGDK 的第三方库(任何以 db 为前缀的命令),但
我正在关注 Brian Harvey 从 2011 年开始在 UC Berkeley site 上的 SICP 讲座。 .他正在使用 STk interpreter教这门课,我正在使用带有 DrRac
在这段代码中,为什么在运算符重载中无法访问我的类的私有(private)字段? (请注意,这只是一个 MRE,不是完整代码) template class Frac template Frac o
在命名命名空间类中,我将一个类(位于全局命名空间中)声明为友元。 但是,后一个类不能访问前一个类的私有(private)成员。为什么是这样?有什么办法可以解决吗? Bob.h namespace AB
我是一名优秀的程序员,十分优秀!