大家好,我是 DongGu ,是一名软件工程专业大二的学生,写博客一方面是为了记录自己的学习过程,把自己犯的错误进行分享。但由于水平有限,博客中难免会有一些错误出现,有纰漏之处恳请各位大佬不吝赐教!有任何问题可以评论 或者 ___> QQ联系(1521839703) 个人博客网站也搭好啦: dongguxy.top
1. 关于虚析构的认识
先看上面3种情况,其实设不设为虚函数都没问题, 就是怕delete一个动态分配的对象,且动态类型为子类的时候,会出现指针的静态类型与被删除对象的动态类型不符合的情况
- 我们都知道, 有了虚函数,就有了虚函数表,有了虚函数表,就会继承父类的虚函数表的内容,如果子类没有重写父类的虚函数方法,那么该函数地址不会变化,如果写了,那么就会更新虚函数表的函数地址,
- 然后我们又想,如果父类实现虚析构函数,子类没有实现怎么办? 我们要记住,如果父类有虚函数,系统会给我们实现一个默认构造函数,默认析构函数,默认拷贝构造函数,后面会讲,
- 调用虚函数的时候,就会读到虚函数表的地址,再通过偏移量去调用,因为虚函数表的函数位置是不变的,函数地址在编译前就确定了的
测试代码:
#include<algorithm>
#include<iostream>
using namespace std;
class Father {
public:
int fa;
virtual ~Father(){}
virtual void i() {}
};
class Son:public Father{
public:
int s;
virtual void i() {}
~Son() {}
};
int main()
{
Father* f = new Son;
f->i();
f->Father::i();
f->fa = 10;
delete f;
return 0;
}
2. 虚函数
测试代码:
#include<algorithm>
#include<iostream>
using namespace std;
class Father {
public:
int fa;
virtual ~Father() { cout << "~Father\n"; }
virtual void i() {}
};
class Father2 {
public:
int fa2;
virtual ~Father2() { cout << "~Father2\n"; }
virtual void j() {}
virtual void k() {}
};
class Son:public Father,public Father2{
public:
int s;
virtual void i() {}
virtual void k() {}
virtual ~Son() { cout << "~Son\n"; }
};
int main()
{
Son* s = new Son;
s->k();
Father* f = s;
f->i();
f->fa = 10;
Father2* f2 = s;
f2->j();
f2->k();
f2->fa2 = 2;
delete f2;
return 0;
}
3. 虚基类
- 虚继承父类,类中有虚函数
测试代码:
#include<algorithm>
#include<iostream>
using namespace std;
class B {
public:
int b;
};
class B1 :public virtual B {
public:
int b1;
virtual void fun() { cout << "B1 fun\n"; }
};
int main() {
B1* b1 = new B1;
b1->b1 = 10;
b1->b = 3;
b1->fun();
return 0;
}
-
虚继承父类,父类有虚函数
-
当一个类虚继承继承多个父类的时候
测试代码
#include<algorithm>
#include<iostream>
using namespace std;
class B {
public:
int b;
};
class B1 :public virtual B {
public:
int b1;
virtual void fun() { cout << "B1 fun\n"; }
};
class B2 : public virtual B {
public:
int b2;
};
class C {
public:
int c;
};
class A :public B1, public B2, public C {
public:
int a;
};
int main() {
A a;
a.b = 10;
a.b1 = 3;
a.b2 = 4;
a.c = 5;
a.a = 6;
B1* b1 = new A;
b1->b = 10;
b1->b1 = 20;
b1->fun();
return 0;
}
- 多继承,都有虚函数时,就相当于,每个类中包含虚函数表,虚基类表,数据成员,如果子类有虚函数,那么该虚函数表和第一个父类共用一个虚函数表
测试代码如下:
#include<algorithm>
#include<iostream>
using namespace std;
class B {
public:
int b;
};
class B1 :public virtual B {
public:
int b1;
virtual void fun() { cout << "B1 fun\n"; }
};
class B2 : public virtual B {
public:
int b2;
virtual void fun1() { cout << "B1 fun\n"; }
};
class C {
public:
int c;
virtual void func() { cout << "c fun\n"; }
};
class A :public B1, public B2, public C {
public:
int a;
virtual void funa() { cout << "a fun\n"; }
};
int main() {
A *a = new A;
a->b = 10;
a->b1 = 3;
a->b2 = 4;
a->c = 5;
a->a = 6;
a->fun();
a->fun1();
a->func();
a->funa();
B1* b1 = new A;
b1->b = 10;
b1->b1 = 20;
b1->fun();
B2* b2 = new A;
b2->b = 10;
b2->b2 = 20;
b2->fun1();
return 0;
}
总结
虚函数怎么访问呢,虚基类怎么访问呢? 就是通过this指针移到该静态类型的首地址去,然后通过调用虚函数表,虚基类表取查找地址,再访问
|