虚函数和抽象类

发布于 2023-04-22  352 次阅读


虚函数

虚函数本质上意思就是在基类声明这个函数的接口类型,可以在继承时重新编写这个函数的定义,关键在于接口要和基类一样。这样的好处主要是可以用基类的指针和引用调用派生类的方法。

#include <iostream>
using namespace std;
class Parent {
public:
    virtual void f() {
        cout << "A::f()" << endl;
    }
};

class Child : public Parent {
public:
    void f() {
        cout << "B::f()" << endl;
    }
};

int main()
{
    Parent *p = new Child();
    p->f();
    return 0;
}

// or quote
// int main()
// {
//     Child b;
//     Parent &a = b;
//     a.f();
//     return 0;
// }

输出:

B::f()

如果不加 virtual 则输出为:

A::f()

关于虚函数表的问题:

#include <iostream>
using namespace std;
class X {
    int i;
    virtual void f();
    virtual void g();
};

int main()
{
    cout << sizeof(X) << ' ' << sizeof(int *) << endl;     
    return 0;
}

问题由这段代码引出,输出为:

16 8

[参考文章]()

每个有虚函数的类都有一个虚函数表,每个该类的实例(对象)都有一个指向虚表的指针,一个指针的大小为 8 Bytes。

img

然后一个 int 的大小为 4 Bytes,加起来等于 12,那为什么会是 16 呢?

计组小测有一道题是内存对齐,我错了,于是这提醒我了,我计组学得好烂,该努力了(bushi),更重要的是这提醒我了,为了方便机器读取,C++在编译的时候应该是进行了内存对齐的,于是一个 int 也是用了 8 Bytes 来储存。

为了验证猜想,又增加了一个 int 和两个 int 进行验证,结果分别为 1624 。初步说明我的猜想正确,要严格证明我的猜想正确很麻烦,我大概是没有那能力的,就不严格证明了。

纯虚函数

纯虚函数的声明:

class Abstract {
public:
    virtual void f() = 0;
};

作用和虚函数差不多,定义好一个接口,但在 Abstract 类中不对这个方法进行实现,而是在继承这个类的时候派生类必须实现这个方法。区别在于含有纯虚函数的类被称为抽象类,抽象类不能进行实例化,即没法 new 一个抽象类的对象。继承该抽象类的派生类中必须进行抽象类中纯虚函数的实现。


整天不想事儿,就想着干饭