一起学习交流~

c/c++细节知识点 15虚函数纯虚函数抽象类

c++面试准备 laomuji 2周前 (09-13) 48次浏览 已收录 0个评论

查看类结构

打开vs的命令行工具
查看某个类的结构

cl /d1  reportSingleClassLayout类名 文件名

查看所有类的结构

cl /d1 reportAllClassLayout 文件名

虚函数

/*
虚函数的主要作用是实现了多态,进行动态绑定
实现了用父类指针指向子类对象,通过父类指针调用子类成员函数。

动态绑定就是在运行时根据对象的实际类型来调用对应的函数

包含虚函数的类(不是对象)存在一个虚表,虚表是一个指针数组指向虚函数的地址
所以虚表的大小就是虚函数个数*指针大小

每个存在虚函数的对象都会存在一个虚指针,用来指向自己所使用的虚表
在编译阶段编译器会自动向拥有虚函数的类中添加一个*vfptr
*/

class Class15_1 {
    void func1() {cout << "func1" << endl;}
    void func2() { cout << "func2" << endl; }
    virtual void vfunc1() { cout << "vfunc1" << endl; }
    virtual void vfunc2() { cout << "vfunc2" << endl; }
};
class Class15_2 {
    void func1() { cout << "func1" << endl; }
    void func2() { cout << "func2" << endl; }
    void func3() { cout << "func1" << endl; }
    void func4() { cout << "func2" << endl; }
};
/*
使用vs的命令行分析类的大小和虚表信息等
cl /d1  reportSingleClassLayoutClass15_1 C:\Users\61436\Desktop\interview\ccpp\ccpp\demo15虚函数纯虚函数抽象类.cpp
*/
int main15_1() {
    return 0;
}

/*
虚函数也可以被继承
有以下四种情形

单继承,不覆盖虚函数
父类虚函数子类虚函数按照顺序放在虚表中

单继承,覆盖虚函数
子类的虚函数会覆盖父类的虚函数

多继承,不覆盖虚函数
什么父类指针调用的就是什么函数
不同父类不相互影响
每个父类拥有的是单独的虚指针,各自占用内存
每个父类的虚函数按照继承的顺序左往右依次排列

多继承,覆盖虚函数
子类的虚函数会覆盖所有父类的虚函数

抽象类
存在纯虚函数的类叫做抽象类

虚基类
类D继承类BC,类BC继承类A,此时D中有两份A的成员
如果只想要保存一份A的成员
那么BC在继承A时使用虚拟继承
如
public B : virtual public A{}
public C : virtual public A{}
*/

class Class15_2_A {
public:
    void func1() { cout << "func1" << endl; }
    //A的vfunc1并不是虚函数,所以Class15_2_A指针调用的仍然是A的vfunc1
    void vfunc1() { cout << "A vfunc1" << endl; }
    virtual void vfunc2() { cout << "A vfunc2" << endl; }
};

class Class15_2_B : public Class15_2_A{
public:
    //注意 从B开始才作为虚函数
    //不会对A造成影响
    virtual void vfunc1() { cout << "B vfunc1" << endl; }
    virtual void vfunc2() { cout << "B vfunc2" << endl; }
};

class Class15_2_C : public Class15_2_B {
public:
    virtual void vfunc1() { cout << "C vfunc1" << endl; }
};

int main15_2() {
    //cl /d1  reportSingleClassLayoutClass15_2_C C:\Users\61436\Desktop\interview\ccpp\ccpp\demo15虚函数纯虚函数抽象类.cpp
    Class15_2_A* pf1 = new Class15_2_C;
    pf1->vfunc1();
    Class15_2_B* pf2 = new Class15_2_C;
    pf2->vfunc1();
    return 0;
}

class Class15_3_A {
public:
    virtual void func1() { cout << "A" << endl; }
};
class Class15_3_B {
public:
    virtual void func1() { cout << "B" << endl; }
};
class Class15_3_C {
public:
    virtual void func1() { cout << "C" << endl; }
};
class Class15_3_D : public Class15_3_A, public Class15_3_B, public Class15_3_C {
public:
    //virtual void func1() { cout << "D" << endl; }
};

int main15_3() {
    //cl /d1  reportSingleClassLayoutClass15_3_D C:\Users\61436\Desktop\interview\ccpp\ccpp\demo15虚函数纯虚函数抽象类.cpp
    Class15_3_A* p1 = new Class15_3_D;
    p1->func1();
    Class15_3_B* p2 = new Class15_3_D;
    p2->func1();
    return 0;
}

纯虚函数

/*
存在纯虚函数的类称作抽象类
抽象类无法实例化
只有子类继承该抽象类后重写了父类的纯虚函数,才能进行实例化

抽象类一般作为接口使用
用抽象类作为指针,调用不同的实例,起到了接口的作用
*/

class Class15_4_A {
protected:
    int num1;
    int num2;
public:
    Class15_4_A(int x,int y) {
        num1 = x;
        num2 = y;
    }

    void showNum() { cout << num1 << " " << num2 << endl; }
    virtual void calc() = 0;//无论有没有实现其实都是相当于没有实现
    //virtual void calc() = 0 {}//这样写也可以s
};

class Class15_4_B : public Class15_4_A{
public:
    Class15_4_B(int x,int y):Class15_4_A(x,y) {}
    void calc() {
        cout << num1 + num2 << endl;
    }
};
class Class15_4_C : public Class15_4_A {
public:
    Class15_4_C(int x, int y) :Class15_4_A(x, y) {}
    void calc() {
        cout << num1 - num2 << endl;
    }
};

int main15_4() {
    Class15_4_A* p;
    p = new Class15_4_B(123,3);
    p->showNum();
    p->calc();
    p = new Class15_4_C(123, 3);
    p->showNum();
    p->calc();
    return 0;
}

/*
虚基类和虚继承
*/

class Class15_5_A {
public:
    int a;
};
class Class15_5_B :virtual public Class15_5_A {
public:
    int b;
};
class Class15_5_C :virtual public Class15_5_A {
public:
    int c;
};

class Class15_5_D :Class15_5_B, Class15_5_C {
public:
    int d;
    void show() {
        //BC虚继承A,A是D的虚基类,此时a不会冲突
        //b c中只存在一份a
        cout << a << b << c << endl;
    }
};
喜欢 (0)
订阅评论
提醒
guest
0 评论
内联反馈
查看所有评论