阿秀C++笔记-学习记录

81.C++中的组合和继承相比的优缺点

在C中组合一对象系用描述对象包对象系组一个拥对象例其变合类的含的现。这的量类当有员被创建。

以下一个示例,展示了在C++中如何实现组合关系:

class Engine {
    // Engine class definition...
};

class Car {
    Engine engine;
    // Other member variables and functions...
};

int main() {
    Car car;
    // Access car's engine through the member variable:
    car.engine.start(); // Example method call
    
    return 0;
}

在上面的示例中,Car 类中的 engine 成员变量是一个 Engine 类的对象。通过组合,Car 类中的每个对象都拥有一个引擎对象作为其一部分。在主函数中,我们可以通过 car.engine 来访问 Car 对象的引擎,并调用相关方法。

需要注意的是,组合关系不同于继承关系。在组合中,对象之间的关系是 “has-a”,而在继承中,对象之间的关系是 “is-a”。组合关系更多地体现了对象之间的整体与部分的关系。

组合也就是设计类的时候把要组合的类的对象加入到该类中作为自己的成员变量。

组合的优点:

①:当前对象只能通过所包含的那个对象去调用其方法,所以所包含的对象的内部细节对当前对象时不可见的。

②:当前对象与包含的对象是一个低耦合关系,如果修改包含对象的类中代码不需要修改当前对象类的代码。

③:当前对象可以在运行时动态的绑定所包含的对象。可以通过set方法给所包含对象赋值。

组合的缺点:①:容易产生过多的对象。②:为了能组合多个对象,必须仔细对接口进行定义。

继承

继承是Is a 的关系,比如说Student继承Person,则说明Student is a Person。继承的优点是子类可以重写父类的方法来方便地实现对父类的扩展。

继承的缺点有以下几点:

①:父类的内部细节对子类是可见的。

②:子类从父类继承的方法在编译时就确定下来了,所以无法在运行期间改变从父类继承的方法的行为。

③:如果对父类的方法做了修改的话(比如增加了一个参数),则子类的方法必须做出相应的修改。所以说子类与父类是一种高耦合,违背了面向对象思想。

85.函数调用过程栈的变化,返回值和参数变量哪个先入栈?

1、调用者函数把被调函数所需要的参数按照与被调函数的形参顺序相反的顺序压入栈中,即:从右向左依次把被调函数所需要的参数压入栈;

2、调用者函数使用call指令调用被调函数,并把call指令的下一条指令的地址当成返回地址压入栈中(这个压栈操作隐含在call指令中);

3、在被调函数中,被调函数会先保存调用者函数的栈底地址(push ebp),然后再保存调用者函数的栈顶地址,即:当前被调函数的栈底地址(mov ebp,esp);

4、在被调函数中,从ebp的位置处开始存放被调函数中的局部变量和临时变量,并且这些变量的地址按照定义时的顺序依次减小,即:这些变量的地址是按照栈的延伸方向排列的,先定义的变量先入栈,后定义的变量后入栈;

对于大部分的编程语言和操作系统,被调用函数通常会在进入函数之前保存调用者函数的栈底地址(也称为帧指针,Frame Pointer)和栈顶地址。

下面是一般的函数调用过程:

  1. 当一个函数被调用时,调用者函数的指令执行流会被跳转到被调用函数的入口点。

  2. 在被调用函数中,首先会将调用者函数的栈底地址保存到栈中,这个操作一般由 push ebp 指令完成。

  3. 接下来,将当前栈顶地址(esp)保存到ebp寄存器中,以成为新的栈底地址。这个过程使用 mov ebp, esp 指令完成。

  4. 这样,被调用函数就保存了调用者函数的栈底地址,并且在ebp寄存器中保存了新的栈底地址,可以使用ebp来访问函数参数和局部变量。

  5. 函数执行完成后,会使用 pop ebp 指令将保存的栈底地址还原为调用者函数的栈底地址,以返回到调用者函数。

这种操作可以建立一个新的函数执行帧,使得被调用函数能够正确地访问参数和局部变量,并在函数执行完毕后能够正确返回到调用者函数的执行位置。

需要注意的是,上述过程是一种常见的方式,但并非所有编程语言和操作系统都采用相同的方式来管理函数调用的栈帧。具体的实现可能会有所不同。

在典型的函数调用过程中,被调函数通常会使用栈来存放局部变量和临时变量。栈的延伸方向可以是向下或向上,取决于特定的体系结构和操作系统约定。在大多数情况下,栈的延伸方向是向下的,也就是地址依次减小。

对于采用向下延伸的栈,函数中的局部变量和临时变量会从ebp指针处往下分配内存空间,并按照变量定义的顺序依次排列。具体步骤如下:

  1. 将ebp的值保存到临时寄存器,通常使用mov指令将ebp的值存储到esp或者eax等寄存器。

  2. 将esp的值赋给ebp,将ebp的值设置为当前的栈顶地址,即将ebp指向当前函数的栈帧底部。

  3. 为该函数的局部变量和临时变量分配内存空间。根据变量的类型和大小,在ebp的位置逐渐减小的方向上分配适当的内存空间。

  4. 变量根据定义的顺序依次被分配在栈上,先定义的变量会在栈中较低的位置。

  5. 在函数的执行过程中,可以通过使用ebp加上偏移量来访问局部变量和临时变量。

需要注意的是,这种栈帧的实现方式是一种常见的做法,但并非所有的编程语言和操作系统都采用相同的方式。具体的实现可能会根据编程语言、编译器或操作系统的不同而有所变化。

你可能感兴趣的:(CPP,c++,linux,学习,求职)