IE盒子

搜索
查看: 136|回复: 1

C++开发高频面试题 21-25

[复制链接]

3

主题

9

帖子

19

积分

新手上路

Rank: 1

积分
19
发表于 2023-3-22 17:11:45 | 显示全部楼层 |阅读模式
21.构造函数为什么可以声明为虚函数,但不可以声明为纯虚函数?


在C++中,构造函数可以声明为虚函数,但不能声明为纯虚函数。这是因为纯虚函数是一个没有实现的虚函数,需要由子类来实现,而构造函数是用来创建对象的,必须被实现。如果将构造函数声明为纯虚函数,则无法创建对象,因为没有实现。
虚函数是为了支持多态性而引入的,而构造函数的多态性并不像虚函数那样有意义,因为构造函数的任务是构造对象,而不是多态地派生对象。虚函数的调用是在运行时动态绑定的,而构造函数的调用是在编译时静态绑定的。如果将构造函数声明为虚函数,会造成意想不到的问题,比如调用构造函数时会调用到子类的虚函数,但此时子类对象还未被构造完成,会导致未定义行为。
因此,构造函数不能声明为纯虚函数,但可以声明为虚函数,这样可以在构造函数中调用虚函数,达到一定的多态效果。但要注意在构造函数中调用虚函数时的注意事项,如避免多态行为的副作用和对象的未定义状态等。



22.为什么析构函数一般写成虚函数  



析构函数一般写成虚函数是为了支持多态,确保当一个基类指针指向一个派生类对象时,delete操作可以正确地调用该对象的析构函数。如果析构函数不是虚函数,那么在使用基类指针释放派生类对象时,只会调用基类的析构函数,而不会调用派生类的析构函数,会导致资源泄漏和未定义行为。因此,为了避免这种情况,析构函数一般都要声明为虚函数,从而实现多态。



23.C++中的重载、重写(覆盖)和隐藏的区别?



C++中的重载、重写(覆盖)和隐藏是面向对象编程中重要的概念,它们的含义和用法如下:


  • 重载(overload):在同一个作用域内,可以定义多个名称相同但参数类型和数量不同的函数或运算符,这就是重载。重载函数或运算符会根据实参的类型和数量来自动匹配调用正确的函数或运算符。例如:
int add(int x, int y) {
    return x + y;
}

double add(double x, double y) {
    return x + y;
}

int main() {
    int a = add(1, 2);
    double b = add(1.1, 2.2);
    return 0;
}
2.重写(覆盖,override):在派生类中重新定义(覆盖)基类的虚函数,使得基类指针或引用在调用虚函数时能够动态绑定到派生类中的函数。例如:
class A {
public:
    virtual void func() {
        std::cout << "A::func" << std::endl;
    }
};

class B : public A {
public:
    virtual void func() override {
        std::cout << "B::func" << std::endl;
    }
};

int main() {
    A* pa = new B();
    pa->func(); // 输出 B::func
    delete pa;
    return 0;
}
3. 隐藏(hide):在派生类中定义了与基类同名的函数或变量,就会隐藏基类中的同名函数或变量。例如:
class A {
public:
    void func() {
        std::cout << "A::func" << std::endl;
    }
};

class B : public A {
public:
    void func() {
        std::cout << "B::func" << std::endl;
    }
};

int main() {
    B b;
    b.func(); // 输出 B::func
    b.A::func(); // 输出 A::func
    return 0;
}
总结:重载是指在同一作用域中定义多个名称相同但参数不同的函数或运算符;重写(覆盖)是指在派生类中重新定义基类的虚函数,使得基类指针或引用在调用虚函数时能够动态绑定到派生类中的函数;隐藏是指在派生类中定义了与基类同名的函数或变量,会隐藏基类中的同名函数或变量。

24.C++的多态如何实现?



C++中的多态性可以通过虚函数实现。在面向对象程序设计中,多态性指的是一个类的实例对不同的方法调用会有不同的行为。多态性使得不同的子类可以以相同的方式使用。实现多态性的方式是通过定义虚函数。
在基类中定义虚函数,然后在派生类中重写该函数。当调用一个对象的虚函数时,实际调用的是该对象所属类的虚函数,而不是该对象的静态类型所定义的函数。
下面是一个简单的示例,演示如何通过虚函数实现多态性:

#include <iostream>
using namespace std;

class Shape {
   public:
      virtual double area() = 0;
};

class Rectangle: public Shape {
   public:
      Rectangle(double w, double h) {
         width = w;
         height = h;
      }

      double area() {
         return width * height;
      }

   private:
      double width;
      double height;
};

class Circle: public Shape {
   public:
      Circle(double r) {
         radius = r;
      }

      double area() {
         return 3.14 * radius * radius;
      }

   private:
      double radius;
};

int main() {
   Shape *shape;
   Rectangle rec(10,7);
   Circle cir(5);

   shape = &rec;
   cout << "矩形面积:" << shape->area() << endl;

   shape = ○
   cout << "圆形面积:" << shape->area() << endl;

   return 0;
}

在这个示例中,Shape 是一个抽象基类,它定义了纯虚函数 area()。Rectangle 和 Circle 是派生类,它们都实现了 area() 函数。在 main() 函数中,定义了一个 Shape 类型的指针,它指向一个 Rectangle 对象和一个 Circle 对象。通过调用 shape->area() 来计算不同形状的面积。在运行时,会根据对象的实际类型调用相应的函数,实现多态性。

25.C++有哪几种的构造函数?


在 C++ 中,有以下几种构造函数:

  • 默认构造函数:没有参数的构造函数,如果没有显式定义,则编译器会自动生成一个默认构造函数。
  • 带参数的构造函数:有参数的构造函数,可以用来初始化对象的成员变量。
  • 拷贝构造函数:用来复制对象的构造函数,用于创建一个新对象,并将其初始化为现有对象的精确副本。
  • 移动构造函数:用于将右值引用作为参数,将其内容移动到一个新对象中,而不进行副本复制。
其中,1 和 2 是必备的构造函数,而 3 和 4 是可选的构造函数。除此之外,C++11 还引入了委托构造函数和析构函数等新特性。
<hr/>
回复

使用道具 举报

3

主题

6

帖子

14

积分

新手上路

Rank: 1

积分
14
发表于 6 天前 | 显示全部楼层
发发呆,回回帖,工作结束~
回复

使用道具 举报

您需要登录后才可以回帖 登录 | 立即注册

本版积分规则

快速回复 返回顶部 返回列表