帮助我理解这一点,如果我考虑所有 C++ 标准,包括 C++11,那么说我可以处理的唯一对象是类的实例是正确的吗?
其他玩家,例如 lambdas 呢?POD 的一个实例被认为是一个对象?
我知道这听起来像是一个小细节,但大多数时候,当我在定义什么是对象和什么不是对象时遇到此类问题时,我发现其他语言的概念很难比较,尤其是在函数式 OOP 语言中。
如果我考虑所有 C++ 标准,包括 C++11,那么说我可以处理的唯一对象是类的实例是正确的吗?
不,这是不正确的。
在 C++ 中,术语“对象”是指根据赋予对象的属性(例如其类型)给出特定解释的存储区域。
根据 C++11 标准的第 1.8/1 段:
C++ 程序中的构造创建、销毁、引用、访问和操作对象。一个对象是一个存储区域。[注意:函数不是对象,无论它是否像对象那样占用存储空间。—尾注]对象由定义(3.1)、新表达式(5.3.4)或实现(12.2)在需要时创建。对象的属性是在创建对象时确定的。一个对象可以有一个名称(第 3 条)。对象具有影响其生命周期 (3.8) 的存储持续时间 (3.7)。一个对象有一个类型(3.9)。术语对象类型是指创建对象的类型. 一些对象是多态的(10.3);该实现生成与每个此类对象相关联的信息,从而可以在程序执行期间确定该对象的类型。对于其他对象,其中找到的值的解释取决于用于访问它们的表达式的类型(第 5 条)。
所以基本上anint
是一个对象,一个POD的实例是一个对象,当然一个类类型的实例也是一个对象。在 OOP 中,术语“对象”通常仅表示后一个实体——但在 C++ 中并非如此。
其他玩家,例如 lambdas 呢?
Lambda 实际上是定义未命名函子的语法糖(第 5.1.2/1 段):
Lambda 表达式提供了一种简洁的方式来创建简单的函数对象。[...]
另外(根据第 5.1.2/2 段):
对 lambda 表达式的求值会产生一个临时纯右值 (12.2)。这个临时的称为闭包对象。[...] [注意:闭包对象的行为类似于函数对象(20.8)。——<em>尾注]
因此,lambda 是表达式,其求值会导致创建一个临时对象(所以是的,在某种意义上可以说 lambda 也是对象,或者更确切地说,它们产生一个对象)。
传统的OOP倾向于将“对象”的概念定义为携带方法和数据的“多态实体”,并且可以从其他对象和算法中引用。
对象的 C++ 定义本质上是“任何事物都需要空间来保持状态”。这导致 C++“对象”具有“值行为”和“方法”不一定是成员的主要区别,并且对象不一定需要支持运行时多态性。
遵循传统 OOP 定义的 C++ 程序,以 (smart)-(base)-(pointers|reference) 引用的类结束,使用间接机制作为在运行时解决多态性的关键。
现代 C++ 使用对象作为具有值复制或移动语义,并倾向于在编译时使用模板和通用算法和类型特征来解决多态性。
这两件事不是相互对立的,但 C++ 有意将两者合并,因此减少了传统 OOP 的“对象”定义(要引用的类的实例),实际上是削减了一半的 C++ 特性和可能性。
关于 lambda,严格意义上来说,它们是返回匿名类型对象的表达式(不是对象本身)。
所以说它们是对象是不恰当的:a+b
它本身不是一个对象:它产生一个对象(表达式的结果)。同样适用于[](){}
:它本身不是一个对象:它产生一个对象,你甚至可以存储,比如
auto fn = [](){}; //create a lambda and assign to fn.
fn(); //just calls it
fn 类型类似于
class lambda_uniquename
{
public:
void operator()()
{}
};
这里的对象不是lambda
类,而是fn
变量。
在 C++ 中,对象是具有关联类型的存储区域
例如一个int
该区域不一定是连续的
举个例子,一个对象的虚拟多重继承部分可以(在某种意义上,在某些情况下存在它必须存在的地方)分布在