可以实例化什么?(这是一个关于IT技术的问题)

5

C++中可以实例化哪些类型?

我知道以下每个直接创建单个Foo实例:

Foo bar;
Foo *bizz = new Foo();

然而,对于内置类型呢?下面的代码会创建两个int实例吗?还是说“实例”这个词用错了,只是在分配内存?

int bar2;
int *bizz2 = new int;

指针呢?上面的例子创建了一个int *实例,还是只分配了内存给int *

使用像423.14这样的字面量也会创建实例吗?

我听说如果你不能对一种类型进行子类化,那它就不是一个类,如果它不是一个类,它就无法被实例化。这是真的吗?

5个回答

4
只要我们谈论C ++,唯一权威的来源就是ISO标准。 它从不使用“实例化”一词来表示类和函数模板之外的任何内容。
然而,它确实使用了“实例”这个词。例如:
每个具有自动存储期(3.7.2)的对象的实例都与其块的每个条目相关联。
请注意,在C ++术语中,int lvalue也是一个“对象”:
C++程序中的构造物创建、销毁、引用、访问和操作对象。对象是存储区域。
由于new明显创建存储区域,因此任何这样创建的东西都是一个对象,并且遵循规范的先例,可以称为实例。

这可能是迄今为止最好的答案。C++标准和一般面向对象编程术语之间的差异很有趣。大多数面向对象编程程序员可能不会将像int x这样的东西称为int的实例,也不太可能将int称为对象;但尽管如此,将其称为对象也是技术上正确的。 - Charles Salvia
1
是的,正如Pavel所引用的,“instance”在通常的OOP意义上根本没有被使用,因为它说的是“一个对象的实例”,而不是“一个类型的实例”。我认为它可以被替换为“另一个具有...的对象”,并且意思相同。我猜想大多数OOP程序员不会将int称为对象,因为他们接受的是Java的培训,在Java中,确实int不是Object。更纯粹的OOP语言不会为内置类型做出任何例外,因此它们的整数是对象。在Ruby中,您可以动态地猴子补丁方法到表示它们的类中,使3.minutes等于180。 - Steve Jessop

3
据我所知,您在这里实际上只是询问术语。C++标准所作出的唯一真正区分是POD类型和非POD类型,其中非POD类型具有用户定义的构造函数、成员函数、私有变量等特性,而POD类型则没有。像int和float这样的基本类型当然是PODs,PODs的数组和PODs的C-structs也是如此。
除了(并且与)C++重叠之外,在面向对象编程中,“实例”的概念通常指为对象在内存中分配空间,然后使用构造函数进行初始化。无论是在堆栈还是堆上完成这个过程,或者在内存中的任何其他位置完成这个过程,都基本无关紧要。
但是,C++标准似乎认为所有数据类型都是“对象”。例如,在3.9中它说:
"The object representation of type T is the sequence of N unsigned char objects taken up by the object of type T, where N equals sizeof(T)..."
因此,C++标准本身所做出的唯一区分是POD与非POD。

引用标准非常好。谢谢!看起来是朝着正确方向迈出的一步。 - strager
你的陈述“像 intfloat 这样的基本类型当然是非 POD 的,同样,POD 数组和 C-structs 也是非 POD 的。”似乎不正确。你的意思是要将“非 POD”替换为“POD”,反之亦然吗? - strager
好的,抱歉 - 那是一个打字错误。我稍微编辑了一下帖子,并纠正了那个错误。 - Charles Salvia
POD结构体确实有构造函数(就像任何没有明确定义构造函数的结构体/类/联合体一样)。这些构造函数被称为“平凡的”,正如C++规范所称,但它们仍然存在。 - Pavel Minaev
True:POD结构体具有隐式构造函数。如果您实际定义了构造函数,则该对象不再是POD。 - Charles Salvia

2

“实例”的概念并不是C++本身固有的,基本上你有“具有构造函数和没有构造函数的东西”。

因此,所有类型都有一个大小,例如int通常为4个字节,带有几个int的结构体将是8个字节等等。现在,在该结构体上添加一个构造函数,它开始看起来(并且行为)像一个类。更具体地说:

int foo; // <-- 4 bytes, no constructor

struct Foo
{
  int foo;
  int bar;
}; // <-- 8 bytes, no constructor

struct Foo
{
  Foo() : foo(0), bar(0) {}
  int foo;
  int bar;
}; // <-- 8 bytes, with constructor

现在,这些类型中的任何一种都可以存在于堆栈或堆上。当你在堆栈上创建一个东西,比如上面的“int foo;”,它会在其作用域结束时消失(例如在函数调用结束时)。如果你使用“new”创建了某些东西,它会放在堆上,并在内存中获得自己的位置,直到你调用“delete”为止。在两种情况下,如果有构造函数,它将在实例化期间调用。

2

在C++中,“实例”和“实例化”仅与类相关。

但请注意,这些也是可以具有会话意义的英语单词。 “指针”显然是英语用法中的一类事物,指针显然是该类的实例

但在C ++中,“指针”不是一个类,“指针”不是类的实例

另请参见 - 针尖上的天使数量


然而,还有其他语言(例如Smalltalk),其中一切都是对象,因此您确实会得到整数的实例等。 - pm100
“在 C++ 中,'instance' 和 'instantiate' 仅与类相关”——出处? - Pavel Minaev

1

使用"new int"不太常见,但是是允许的。甚至可以向构造函数传递0或1个参数。我不确定"new int()"是否表示它被初始化为0(我猜测是),与"new int"不同。

当您在堆栈上定义一个值时,通常不会称之为"分配内存"(尽管理论上它正在获取堆栈上的内存,但该值可能仅存在于CPU寄存器中)。

字面常量不一定会在程序内存中获得地址;CPU指令可以直接编码数据(例如将42放入寄存器B)。可能任意浮点常数都有一个地址。


我主要想知道一个 int 和其他内置类型是否可以被实例化。根据其他答案和您的回答,我认为一个 int 有一个构造函数,因此可以有一个实例,是吗? - strager
不,int没有构造函数。C++区分POD和非POD类型,其中POD类型可以有构造函数、成员函数、私有成员变量等,而非POD类型则不能。 - Charles Salvia
POD结构体确实有构造函数。它们没有非平凡的构造函数。 - Pavel Minaev

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