面向对象编程中的类与new关键字

在面向对象的编程中,总是先定义一个类,然后在定义一个对象并用new来构建它.
类是抽象的,也就是给编译器看的,编译器照着类的样子在程序中"画"出一个对象.这到也说的过去.
但是,很多时候,构建对象往往是在程序运行时构建的.那么既然说类是抽象的,在内存中并不存在.那应该也不存在于exe文件里面,要是他存在于exe文件里面,那系统加载程序就把它加载进去了,又怎能说在内存中不存在呢。而如果在exe里面不存在,那程序运行的时候又是怎么得知该“类”的大小和数据来构建对象的呢?
而如果在exe里面存在,那么直接调用就行了,为什么还要浪费内存去构建一个副本呢

类是用来定义对象包含哪些数据和支持那些操作,也就是说类规定了对象的内存布局和在这块内存上合法的操作。在编译时如果编译器遇到对象的定义,编译器会根据类的定义为对象分配内存(生成分配内存的机器指令或者汇编指令),如果遇到成员函数调用(或者方法调用)编译器会根据类的定义进行类型检查(检查通过就生成调用函数的汇编代码)。

对象是一个实体或者类的实例,占据着一块内存空间,并且可以对他执行一些操作,你也可以简单理解为对象就是一块内存空间, 分配内存就等于定义对象。

内存如何分配是由类定义来决定的,当遇到对象定义或者new,编译器就根据类的定义直接生成分配内存的汇编指令以及调用构造函数的汇编指令(这些在编译时就可以确定)。C++里面如果在定义的时候找不到类的定义编译器就会报错,因为编译器不知道类对象的内存布局和构造函数。

关于你说的类在不在exe里面,这要看是什么语言!有的语言类型信息只存在于编译时、有的语言的类型信息在运行时也存在。追问

我只想知道如果自己做操作系统和编译器,这些东西怎么实现你说的这些木什么用,比如,那个new 操作符你用汇编语言解释一下,分配内存这事情不是操作系统干的吗,不是说每个进程都有固定独立的地址空间吗,既然地址空间都有了,那还需要你分配什么内存?难道你还能动物理内存?这应该是内核才能干的吧

追答

C++代码:

int a;
int b;
int c;
a = 1;
b = 2;
c = 3;
new int[2];
汇编代码:
//push ebp // ebp入栈
//mov ebp, esp // ebp保存栈顶指针
//sub esp, 12 // 为局部变量a、b、c分配12个字节的栈内存
//mov [ebp - 4], 1 // 变量a赋值1
//mov [ebp - 8], 2 // 。。。
//mov [ebp - 12], 3 //。。。
//push 8 // 压入8
//call operator new[] (01F102Fh) // 调用全局new[]函数 分配8个字节的空间。

操作系统是给每个进程创建了一个独立的地址空间,但是这个空间只是你可以引用的地址范围,你在程序里面需要规定那些地址对应的虚拟内存空间用来保存数据(这叫做分配内存),当时实际保存数据的时候,操作系统会将这块虚拟内存对应的页面映射到物理内存。不是给你一个地址范围你就可以随机乱来、随便乱存。

追问

很多程序是在运行的时候来创建对象,比如当你按下一个键时,响应你这个按键操作的函数就是去创建一个对象,如果说new只是空出一块内存,那又是什么东西把类里面的数据般到对象里去,而如果类不在exe里面,这个东西又到哪里去搬数据呢
我就觉得类一定在exe里面,说什么类是抽象的,不占内存,简直就是胡说八道

追答

定义对象的时候,编译器首先会分配内存,然后调用构造函数初始化内存空间,这个两个步骤就完成对象的创建。你要设置对象中的数据的值,要么你就直接访问对象的子对象或者调用成员函数来设置。 程序用到的常量数据都单独保存到一个存储区叫做常量段,包括你在程序中使用的常量数据和常量字符串。这些保存在常量段的数据对于有用的程序是不够用的,所以程序运行的时候还要从外部输入数据。

对于完全编译型的语言来说,类在程序中是不占用存储空间的,只有在某些需要运行时类型信息的地方,类定义的每个对象才会多站一点内存,这是使用运行时类型信息的代价。但是对于解释型语言,情况就会有所不同,编译器首先将源代码编译成某种中间语言,然后在执行的时候EXE的时候,由解释器一行行对中间代码进行解释,所以类的信息在“可执行文件”和运行的时候可能也存在,但是这只是一种实现细节而已。 这种语言生成的可执行文件是不能直接执行的,需要解释器将中间代码翻译成机器指令后才能执行。

程序运行的时候又是怎么得知该“类”的大小和数据来构建对象的呢?
类的定义最终都是要给编译器看,所以编译器在编译的时候完全知道类定义的对象所占用的大小、类对象包含哪些字段、类对象可以执行哪些函数,所以编译器或者解释器遇到类对象的定义时,完全可以直接生成分配内存的和调用构造函数的汇编指令。

我都对你无语了,你如果好好看书,就不会问这些奇葩、不沾边的问题了。

追问

我也是无语了,你说定义对象的时候会分配内存,比如说用"Windows"这个类来定义一个windows对象:Windows windows=null;此时这个所谓的windows对象不过是个空指针而已,何谓分配内存,

追答

这不是对象,你是在说Java语言或者C#语言吧,Windows windows = null; 这里定义的是引用,不是对象,对象还没创建,Java语言中对象的创建需要使用new,null表示该引用没有与任何对象关联,请在书上找 引用和对象的区别。

追问

我慢慢研究

温馨提示:答案为网友推荐,仅供参考
相似回答