C++中的对象是什么?

11
在我开始学习C++的旅程中,我认为对象是与面向对象编程有关的术语。然而,随着我学习的越多,阅读的越多,我发现这并非如此,并且发现“对象”一词具有更加广义的含义。我在网上阅读了很多材料,但我还没有找到清晰/可靠的内容。可能我还没有找到正确的地方。我能够获得标准,其中有关于这个问题的好段落,但正如您所知,标准语言有点困难,信息通常也零散分布。
我的问题:请用简单的英语告诉我,除了面向对象编程之外,在C++中什么是对象?

在内存中有一个地址的东西。 - user2100815
1
请阅读例如http://en.cppreference.com/w/cpp/language/object的内容,该内容与编程有关。 - Stephan Lechner
哇,太棒了,这个资源好厉害啊!我怎么之前没来过这个页面呢?!非常感谢 @Stephan Lechner。 - Kamal Zidan
@KamalZidan.. 如果你想在SO上花些时间,匿名的踩票是你必须习惯的事情。忽略它们并继续前进(除非它们超过每秒1个踩票,那么你的问题可能有严重的问题)。 - Humam Helfawi
感谢@Humam Helfawi。这是一个很棒的知识点。 - Kamal Zidan
存储区域及其关联语义。这段内容来自isocpp超级常见问题解答。编程要素: 对象:作为内存中的值,代表具体实体的一种表示形式。一个对象是可变的,并且具有特定于计算机的实现。 - chedy najjar
5个回答

8

C++11标准非常明确:

1.8 C++对象模型 [ intro.object ]

对象是存储区域。[注意:函数不是对象,无论它是否以对象的方式占用存储空间。—注释结束]

就是这样。对象是一块内存,可以存储数据。

如果你思考一下面向对象Object Orientation,你会发现在旧时代,程序是围绕着操作对象(或数据)的函数组织的,所以更有意义。

术语“对象”早在面向对象之前就已经存在了。

面向对象所做的是将程序组织从围绕函数转变为围绕数据本身——对象

因此出现了术语面向对象

范式变化

在这里,我们看到了从旧时代开始的范式转变:

struct my_object
{
    int i;
    char s[20];
};

void function(my_object* o)
{
    // function operates on the object (procedural / procedure oriented)
}

现在我们所拥有的:

struct my_object
{
    void function()
    {
        // object operates on itself (Object Oriented)
    }

    int i;
    char s[20];
};

2
这个定义比我在C++中预期的要广泛得多,甚至适用于未初始化的内存。 - Mark Ransom
1
也许每个对象都是存储区域,但并不是每个存储区域都是对象 ;) - rwols
1
在我看来,您可以将malloc分配的存储区域视为一个对象。也许不是特别有用的对象,但您仍然可以像处理其他对象一样处理它。 void *myclass *之间唯一的区别在于myclass *具有我可以使用的有用内容。我仍然可以以相同的方式处理内存块,但可能无法以面向对象的方式进行。 - user820304
1
根据标准,即使未初始化的存储也被称为对象。 - Galik
1
由于其不完整性,这个答案非常接近错误。参考标准的同一段落,可以看到一个对象:占用了存储区域,具有生命周期、存储期限和类型 -> 对象类型(唯一)。它还具有构建期和销毁期。 - Oliv
显示剩余3条评论

7

简短回答

根据https://timsong-cpp.github.io/cppwp/n3337/intro.object,一个对象是存储区域。


稍长回答

在传统的面向对象编程(OOP)和面向对象设计(OOD)中,对象有时用于描述对象类,有时用于描述类的实例。

在C++中,classstruct表示类。

C++中的对象可以是classstruct的实例,也可以是基本类型的实例。

以下是一些简单的示例:

int i;

i是一个对象。它与程序可以使用的存储区域相关联。

struct foo { int a; int b;};
foo f;

f 是一个对象。它也与可以被程序使用的存储区域相关联。

int* ptr = new int[200];

ptr 是一个指向200个类型为int的对象的指针。这些对象与程序可以使用的存储区域相关联。


7

不是要贬低现有答案,但它们缺少一个元素(这可以说是一个标准缺陷)。

对象是存储区域。[ 注:函数不是对象,无论它是否以与对象相同的方式占用存储空间。 — 注解结束 ]

定义([basic.def])、new-expression([expr.new])或实现([class.temporary])在需要时创建对象。

对象的属性是在创建对象时确定的。

对象是一块已经构造的存储区域。事实上,大多数情况下,“对象”指的是具有其值和状态的构造实体,而“存储”仅表示它所写入的内存(或其他内容)。

这种差异可能只是一个简单的细节:

// `s` names an object that has been constructed... somewhere.
// That storage will live exactly as long as necessary to back `s`
// as long as the object exists -- no need to worry about it.
std::string s = "hello";

// Using the object
std::cout << s << '\n';

但是你也可以(虽然这很少有用)将对象的生命周期与其存储的生命周期分开:

// `storage` points at a chunk of... storage.
// It hasn't been initialized, nor does it have a type.
void *storage = malloc(sizeof(std::string));

// Now we constructed an `std::string`:
// we have an actual object inhabiting the storage!
std::string *s = new (storage) std::string("hello");

// Using the object, through the pointer we have
std::cout << *s << '\n';    

// Now we destruct the object: it exists no more.
s->~basic_string();

// Now we destroy the storage.
free(storage);

我必须强调,这个最后的例子只是为了演示目的。这种技术你可能不会遇到,并且在这里没有进行任何错误检查。请不要在家中尝试 :)

那么,它与面向对象编程中的"对象"有什么关系呢?嗯...完全没有。"对象"是一个非常通用的术语,而OOP的创始人们只是选择了同样的术语,独立使用它。


2
“对象是已经构造完成的存储区域。” - 这似乎意味着,对于 int n;n 不是一个对象。 - user2100815
2
@NeilButterworth 它是:它是一个默认构造的 int。对于可平凡构造类型,构造不意味着初始化 :) - Quentin
1
@Galik 我的句子有点困难。我的意思是C ++和OOP两个组都不得不给两个完全不同的概念命名,并且他们都选择了“对象”,因为他们觉得这个词很贴切。因此,术语冲突更加可能,这也是因为“对象”这个词太模糊了。如果你能提出更好的措辞,请随意修改 :) - Quentin
1
@NeilButterworth也许我理解错了,但[dcl.init] (https://timsong-cpp.github.io/cppwp/n3337/dcl.init#6)中有一条关于(括号中的引号)“非初始化初始化”的要点。 - Quentin
4
当然,在优化后的构建中实际上并没有在机器级别上完成任何操作,但这在概念上仍然是一种构建。调试运行时也可能将其初始化为某个可识别的值。 - Quentin
显示剩余4条评论

5

参考C++标准(N4618)的§1.8,一个对象:

  1. 在其构造期生命周期销毁期期间占用一段存储区域

  2. 有一个生命周期(对于非平凡对象,它从初始化完成时开始,到析构函数开始时结束);

  3. 具有存储期(静态、动态、线程或自动);

  4. 有一个类型:唯一的对象类型(严格别名)。

  5. 可能有一个名称


关于对象类型

(其他答案已经详细说明了存储期的含义。)

对象类型(或类)是对象的一个独特属性。 对象类型指定了由初始化对象占用的存储区域的含义。因此,从哲学的角度来看,这个含义是独一无二的,对象类型是对象的种类而不是类型。

对于编译器,它只约束可以应用于存储区域的操作集合:与对象类型相关联的方法(在这种情况下,类型由classstruct定义)以及所有将对象作为参数的函数(可见)。

对于程序员,类型还指定了在对象的生命周期内对对象应用一系列操作的后果将是什么。类型包含比编译器实际能够知道的信息要多得多。例如,在检查类型为std::vector<int>的对象an_obj的大小为0之后,程序员知道an_obj.at(0)将始终引发异常,但编译器可能不知道。


-5
在C++世界中,对象是类的实例化。它以某种方式行为(方法/函数),并具有描述其状态的属性(数据成员)。
一个对象有生命周期。它被创建(通过构造函数),它存在,然后它死亡(通过析构函数)。
类就像一个蓝图,通过它你定义对象的行为和属性。

5
与其他语言不同,C++ 中的“对象”并不一定指类的实例。一个 int 就是一个对象。 - Quentin

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接