【C++ 面试 - 面向对象】每日 3 题(三)

✍个人博客:Pandaconda-CSDN博客

专栏地址:http://t.csdnimg.cn/fYaBd

专栏简介:在这个专栏中,我将会分享 C++ 面试中常见的面试题给大家~
❤️如果有收获的话,欢迎点赞收藏,您的支持就是我创作的最大动力

7. 说说 C 语言如何实现 C++ 语言中的重载?

C 语言中不允许有同名函数,因为编译时函数命名是一样的,不像 C++ 会添加参数类型和返回类型作为函数编译后的名称,进而实现重载。如果要用 C 语言显现函数重载,可通过以下方式来实现:

  1. 使用函数指针来实现,重载的函数不能使用同名称,只是类似的实现了函数重载功能

  2. 重载函数使用可变参数,方式如打开文件 open 函数

  3. gcc 有内置函数,程序使用编译函数可以实现函数重载

示例如下:

#include

void func_int(void * a)
{
    printf("%d\n",*(int*)a);  //输出int类型,注意 void * 转化为int
}

void func_double(void * b)
{
    printf("%.2f\n",*(double*)b);
}

typedef void (*ptr)(void *);  //typedef申明一个函数指针

void c_func(ptr p,void *param)
{
     p(param);                //调用对应函数
}

int main()
{
    int a = 23;
    double b = 23.23;
    c_func(func_int,&a);
    c_func(func_double,&b);
    return 0;
}

8. 函数重载的底层实现原理

函数重载是 C++ 中的一种特性,它允许在同一作用域内定义多个具有相同函数名但参数列表不同的函数。函数重载的底层实现原理涉及到编译器的名称修饰和函数调用匹配机制。

  1. 名称修饰(Name Mangling):编译器在编译过程中会对函数名进行修改,以区分不同的重载函数。这是因为在编译后的目标文件中,函数名需要唯一且可识别。编译器会根据不同的参数类型和个数生成唯一的符号来表示重载函数。

  2. 函数调用匹配机制:当调用一个重载函数时,编译器通过参数类型和个数来选择最匹配的函数。它会检查函数调用的参数类型和个数与候选函数的参数类型和个数是否一致,如果一致,则选择该函数作为调用目标。如果没有找到完全匹配的函数,编译器会通过隐式类型转换的规则来进行匹配,选取最佳匹配的函数进行调用。

隐式类型转换包括以下几个方面:

  • 精度提升:比如将一个较小的整数类型转换为较大的整数类型。

  • 数值扩展:比如将一个单精度浮点数转换为双精度浮点数。

  • 类型转换构造函数:如果候选函数的参数类型是用户定义的类类型,并且有相应的类型转换构造函数,编译器可以使用这些构造函数进行类型转换。

需要注意的是,函数重载的决策是在编译期间进行的,而不是在运行时。因此,在调用重载函数时,编译器已经根据重载规则决定了要调用的具体函数,而程序在运行时不需要进行函数的动态查找。

总结来说,函数重载的底层实现原理涉及名称修饰和函数调用匹配机制。编译器通过对函数名进行修改来区分不同的重载函数,并通过参数类型和个数来选择最匹配的函数进行调用。隐式类型转换也是函数重载匹配的一部分。重载决策在编译期间进行,不需要在运行时进行函数的动态查找。

9. 什么是友元函数?

友元函数是 C++ 中的一种机制,它允许在类外部定义的函数或类访问该类的私有或保护成员。这种函数不是类的成员函数,因此没有 this 指针。要在类中声明一个函数为友元函数,需要在类的定义中该函数原型前使用关键字 friend。

例如,考虑一个简单的 Point 类,它表示二维平面上的点。这个类有两个私有成员:x 和 y,分别表示点的 x 坐标和 y 坐标。我们可以创建一个名为 Distance 的友元函数来计算当前点与原点之间的距离。因为 Distance 函数需要访问 Point 类的私有成员 x 和 y,所以我们将其声明为友元函数。

这是相应的代码实现:

class Point {
    friend void Distance(Point& p1);
private:
    int x, y;
};

void Distance(Point& p1) {
    int dx = p1.x;
    int dy = p1.y;
    // ... 计算距离的代码 ...
}

你可能感兴趣的:(#,C++,面试专栏,面试,职场和发展,c++,后端,开发语言)