C++继承、多态、虚指针、虚表

前言

这部分一直以来都是C++基础的重点,这阵子正好在学,记录一下。上课听的时候发现老师其实讲的有点模糊,涉及到的方面也比较多。

继承
#include <iostream>
#include <stdlib.h>

using namespace std;

class Person
{
public:
	virtual void BuyTicket()
	{
		cout << "买票-全价" << endl;
	}
	Person(){
		cout << "父类构造函数" << endl;
	}
	
	virtual ~Person(){
		cout << "fuleixgou" << endl;
	} 
};

class Student : public Person
{
public:
	virtual void BuyTicket(){
		cout << "买票-半价" << endl;
	}
	Student(){
		cout << "子类构造函数" << endl;
	}
	
	virtual ~Student(){
		cout << "zileixgou" << endl;
	} 
};

void Func(Person& p)
{
	p.BuyTicket();
}

int main()
{
	Person ps;
	Student st;

	Func(ps);
	Func(st);

	return 0;
}

运行结果:

父类构造函数
父类构造函数
子类构造函数
买票-全价
买票-半价
zileixgou
fuleixgou
fuleixgou

--------------------------------
Process exited after 0.2538 seconds with return value 0
请按任意键继续. . .

这个应该没有什么问题,但是这里引出一个虚继承!

虚继承

这篇文章,看完应该就可以了解继承和虚继承的整个内存布局了。

多继承

看一下这个例子:

#include <iostream>

using namespace std;

class A {
	int data0;
public:
	A() {
		cout << "A gouzao" << endl;
	}

};

class B : public A {
	int data1;
public:
	B() {
		cout << "B gouzao" << endl;
	}
};

class C : public A {
	int data2;
public:
	C() {
		cout << "C gouzao0" << endl;
	}
};

class D : public B, public C {
	int data3;
public:
	D() {
		cout << "D gouzao" << endl;
	}
};

int main() {
	D d;
	int a;
	cin >> a;
	return 0;
}

运行:

A gouzao
B gouzao
A gouzao
C gouzao0
D gouzao

下面这个对比一下上面那个:

#include <iostream>

using namespace std;

class A {
	int data0;
public:
	A() {
		cout << "A gouzao" << endl;
	}

};

class B : virtual public A {
	int data1;
public:
	B() {
		cout << "B gouzao" << endl;
	}
};

class C : virtual public A {
	int data2;
public:
	C() {
		cout << "C gouzao0" << endl;
	}
};

class D : public B, public C {
	int data3;
public:
	D() {
		cout << "D gouzao" << endl;
	}
};

int main() {
	D d;
	return 0;
}

运行结果:

A gouzao
B gouzao
C gouzao0
D gouzao

--------------------------------
Process exited after 0.3061 seconds with return value 0
请按任意键继续. . .

可以看到区别还是挺大的,大家自行体会一下,同时结合上面关于虚继承的内存分布文章。

多继承虚函数

关于这个部分也有一篇文章,大家可以看一下。
看一下这个例子:

#include <iostream>

using namespace std;

class A {
public:
	void virtual f() {
		cout << "A:f" << endl;
	}
	void virtual g() {
		cout << "A:g" << endl;
	}
	void virtual h() {
		cout << "A:h" << endl;
	}
};

class B : public A {
public:
	void f() {
		cout << "B:f" << endl;
	}
	void virtual g1() {
		cout << "B:g" << endl;
	}
	void virtual h1() {
		cout << "B:h" << endl;
	}
};

int main() {
	A *a;
	B b;
	a = &b;
	a->f();
	b.f();
	return 0;
}

运行:

B:f
B:f

--------------------------------
Process exited after 0.2939 seconds with return value 0
请按任意键继续. . .

可以看到,派生类要是有跟父类同样的函数名是会覆盖掉父类的,那么如何调用到父类的函数呢?应该是要直接创建父类的实例吧?(应该是的)

再看一个实例:

#include <iostream>

using namespace std;

class A {
public:
	void virtual f() {
		cout << "A:f" << endl;
	}
	void virtual g() {
		cout << "A:g" << endl;
	}
	void virtual h() {
		cout << "A:h" << endl;
	}
};

class B {
public:
	void virtual f() {
		cout << "B:f" << endl;
	}
	void virtual g() {
		cout << "B:g" << endl;
	}
	void virtual h() {
		cout << "B:h" << endl;
	}
};

class C {
public:
	void virtual f() {
		cout << "C:f" << endl;
	}
	void virtual g() {
		cout << "C:g" << endl;
	}
	void virtual h() {
		cout << "C:h" << endl;
	}
};

class D :public A,public B, public C{
public:
	void f1() {
		cout << "D:f1" << endl;
	}
	void h1() {
		cout << "D:h1" << endl;
	}

};

int main() {
	D d;
	A *a = &d;
	a->f();
	int c;
	cin >> c;
	return 0;
}

运行:

A:f

当main函数中是这样的话:

D d;
d.f();

这样是编译不通过的,因为f函数指示不明确。

关于虚指针和虚表,额这个在上面两篇文章之中应该已经有很好的体现了。

关于C++的内存模型,这个还是比较重要的,可以跟虚表一起结合,对一个程序有一个比较宏观的看待。

---------------------------未完待续---------------------------------------

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值