C++说爱你不容易面试题-5

常考面试题

  1. 析构函数必须为虚函数吗?构造函数可以为虚函数吗?⭐⭐⭐⭐⭐

    C++默认析构函数不是虚函数,因为申明虚函数会创建虚函数表,占用一定内存,当不存在继承的关系时,析构函数不需要申明为虚函数。

    若存在继承关系时,析构函数必须申明为虚函数,这样父类指针指向子类对象,释放基类指针时才会调用子类的析构函数释放资源,否则内存泄漏

    构造函数不能为虚函数,当申明一个函数为虚函数时,会创建虚函数表,那么这个函数的调用方式是通过虚函数表来调用。若构造函数为虚函数,说明调用方式是通过虚函数表调用,需要借助虚表指针,但是没构造对象,哪里来的虚表指针?但是没有虚表指针,怎么访问虚函数表从而调用构造函数呢?这就成了一个先有鸡还是先有蛋的问题。

  2. 当类存在继承的情况下,我们需要注意什么?⭐⭐⭐⭐⭐

    若存在继承关系时,析构函数必须申明为虚函数,这样父类指针指向子类对象,释放基类指针时才会调用子类的析构函数释放资源,否则内存泄漏

  3. 说说继承类型和访问属性⭐⭐⭐⭐

    当一个类派生自基类,该基类可以被继承为 public、protectedprivate 几种类型。

    我们几乎不使用 protectedprivate 继承,通常使用 public 继承。当使用不同类型的继承时,遵循以下几个规则:

    • 公有继承(public):当一个类派生自公有基类时,基类的公有成员也是派生类的公有成员,基类的保护成员也是派生类的保护成员,基类的私有成员不能直接被派生类访问,但是可以通过调用基类的公有保护成员来访问。
    • 保护继承(protected): 当一个类派生自保护基类时,基类的公有保护成员将成为派生类的保护成员。
    • 私有继承(private):当一个类派生自私有基类时,基类的公有保护成员将成为派生类的私有成员。

    总结: 不管是哪种继承方式,派生类中新增成员可以访问基类的公有成员和保护成员,无法访问私有成员。但是只有公有继承中,派生类的对象能访问基类的公有成员。使用友元(friend)可以访问保护成员和私有成员。

    img
  4. 构造与析构的顺序⭐⭐⭐⭐⭐

    构造顺序:基类构造函数》对象成员构造函数》子类构造函数

    析构顺序:子类析构函数》对象成员析构函数》基类析构函数

    从里向外构造,从外向里析构

    答案解析

    我们给一个例子:

    #include <iostream>
    using namespace std;
    class A{
    public:
         A(){cout<<"A::constructor"<<endl;};
         ~A(){cout<<"A::deconstructor"<<endl;};
    };
    class B{
    public:
         B(){cout<<"B::constructor"<<endl;};
         ~B(){cout<<"B::deconstructor"<<endl;};
    };
    class C : public A{
    public:
         C(){cout<<"C::constructor"<<endl;};
         ~C(){cout<<"C::deconstructor"<<endl;};
    private:
    //    static B b;
         B b;
    };
    class D : public C{
    public:
         D(){cout<<"D::constructor"<<endl;};
         ~D(){cout<<"D::deconstructor"<<endl;};
    };
    
    int main(void){
        C* pd = new D();
        delete pd;
        return 0;
    }
    

    运行结果如下:

    A::constructor
    B::constructor
    C::constructor
    D::constructor
    C::deconstructor
    B::deconstructor
    A::deconstructor
  5. 请说说你对多态的理解⭐⭐⭐⭐⭐

    利用虚函数,基类指针指向基类对象时就使用基类的成员(包括成员函数和成员变量),指向派生类对象时就使用派生类的成员。

    换句话说,基类指针可以按照基类的方式来做事,也可以按照派生类的方式来做事,它有多种形态,或者说有多种表现方式,我们将这种现象称为多态(Polymorphism)

  6. 重载和重写的区别⭐⭐⭐⭐⭐

    1. 重载(overload)

      函数名相同,参数列表不同(参数类型、参数顺序),不能用返回值区分。

      特点:

      (1)作用域相同;

      (2)函数名相同;

      (3)参数列表必须不同,但返回值无要求;

      特殊情况:若某一重载版本的函数前面有virtual关键字修饰,则表示它是虚函数,但它也是重载的一个版本

      作用效果:编译器根据函数不同的参数列表,将函数与函数调用进行早绑定,重载与多态无关,与面向对象无关,它只是一种语言特性。

    2. 重写(override)

      派生类重定义基类的虚

剩余60%内容,订阅专栏后可继续查看/也可单篇购买

<p> - 本专刊适合于C/C++已经入门的学生或人士,有一定的编程基础。 - 本专刊适合于互联网C++软件开发、嵌入式软件求职的学生或人士。 - 本专刊囊括了C语言、C++、操作系统、计算机网络、嵌入式、算法与数据结构等一系列知识点的讲解,并且最后总结出了高频面试考点(附有答案)共近400道,知识点讲解全面。不仅如此,教程还讲解了简历制作、笔试面试准备、面试技巧等内容。 </p> <p> <br /> </p>

全部评论
C* pd = new D(); 4.构造与析构的顺序中,为什么可以定义类型D而接收它的指针是类型C
1 回复 分享
发布于 2021-04-26 15:05
第七个不准确哦,在g++中是这样没错。 但是在VC++中,如果派生类虚继承基类的话,当自己定义新的虚函数的时候,VC++为了防止获取虚函数表时转换到虚基类的巨大开销,这时候他会有一个自己的虚函数指针。还有就是多继承的情况下,如果每个基类都有自己的虚函数,这时候也会导致派生类不止一个虚函数指针。
点赞 回复 分享
发布于 2022-08-22 23:34 江苏
感觉6说的重载与多态无关,和16说的重载是编译期间的多态,有点冲突。其实意思是重载也可以看作是多态在编译期间的表现?感觉可以明确一下多态的定义,要不要把重载的多态纳入进来
点赞 回复 分享
发布于 2023-10-28 21:10 北京

相关推荐

找不到工作死了算了:你已经熟练掌握c语言啦,可以投简历参加秋招了
点赞 评论 收藏
分享
2024-12-09 12:21
门头沟学院 C++
l11hy:今早刚开,已满足
点赞 评论 收藏
分享
评论
点赞
收藏
分享

创作者周榜

更多
牛客网
牛客企业服务