C++13继承多态虚函数

1.继承的本质

// 20190420.cpp : 此文件包含 "main" 函数。程序执行将在此处开始并结束。
//

#include "pch.h"
#include <iostream>
#include <typeinfo>
#include <string>
using namespace std;

/*
继承和多态
1.解释多态
2.RTTI
3.private和protected的区别  继承结构中

继承的本质:代码复用
1.派生类中,从基类继承来的成员的访问限定是什么?
			基类的访问限定			派生类的访问限定     main函数
public
				public				public			yes
				protected			protected		no
				private				不可访问		    no
protected
				public				protected		no
				protected			protected		no
				private				不可访问			no
private
				public				private			no
				protected			private			no
				private				不可访问			no

2.派生类怎么初始化从基类继承来的成员呢?
	通过调用基类相应的构造函数进行初始化,派生类只会初始化自己的成员

3.重载,隐藏,覆盖(基类和派生类同名成员函数之间的关系)
重载:
函数名  参数列表  作用域  =》 重载函数

隐藏:
基类和派生类当中   函数名相同   =》 隐藏

覆盖/重写:
基类和派生类当中  函数的返回值,函数名,参数列表都相同,而且基类的
函数是virtual虚函数,那么称作覆盖关系

4.  继承结构种,默认支持下到上的类型转换
》》》 基类对象  =》 派生类对象    no
》》》 派生类对象  =》  基类对象   yes
》》》 基类指针/引用 =》 派生类对象   yes
》》》 派生类指针/引用 =》 基类对象    no

5. 请解释静态(运行)绑定(函数调用)和动态(运行)绑定(函数调用)
		call 
		call ecx
6. 什么是多态
静态(编译阶段)的多态:函数重载和模板
动态(运行阶段)的多态:虚函数
多态的好处

====》  简单工厂,工厂方法和抽象工厂设计模式  代码  各自的优缺点  

7. RTTI运行时的类型信息
RTTI指针存储在虚函数表vftable当中,指向一段类型字符串

8. 抽象类(不能实例化对象Animal a;)和普通类

9. 析构函数能不能实现成虚函数???
能不能成为虚函数 =》  记录函数地址(vftable)/vfptr(对象)
      对象  地址
virtual 构造函数  no 在构造函数中调用virutal虚函数,请问是静态绑定还是动态绑定?
				在析构函数中调用virtual虚函数,请问是静态绑定还是动态绑定?
static成员方法 =》 virtual函数  no
virtual static void func(){}
inline内联函数
virtual inline int sum(int a, int b){return a + b;} yes!!!!

   什么时候,析构函数必须写成虚析构函数???
10. 调用虚函数一定会发生动态绑定吗???
call Base::show   call ecx/eax
Base b;
b.show();  用对象调用虚函数永远是静态绑定;动态绑定首先要用指针/引用调用虚函数
Derive d;
d.show();

单一继承! vfptr  vftable

多重继承  =》  
1.多重继承有什么坏处?  好处?  怎么解决呢?
2.虚基类是什么?
3.vbptr vbtable

C++的四种类型转换  
const_cast :  
const int a = 10;
int *p = (int*)&a;
int *p = const_cast<int*>(&a);
static_cast
reinterpret_cast  <=>  (Type)
dynamic_cast : 识别RTTI信息的类型转换
*/

class A
{
public:
	A(int data = 0) :ma(data) { cout << "A()" << endl; }
	~A(){cout << "~A()" << endl; }
private:
	int ma;
};
class B : virtual public A 
{
public:
	B(int data = 0) :A(data), mb(data) { cout << "B()" << endl; }
	~B(){cout << "~B()" << endl; }
private:
	int mb;
};
class C : virtual public A
{
public:
	C(int data = 0) :A(data), mc(data) { cout << "C()" << endl; }
	~C(){cout << "~C()" << endl; }
private:
	int mc;
};

class D : public B, public C
{
public:
	D(int data=0):B(data), C(data), md(data) { cout << "D()" << endl; }
	~D(){cout << "~D()" << endl; }
private:
	int md;
};
/*
B::
	vbptr  --->  vbtable  14h
	mb
C::
	vbptr  --->  vbtable  0Ch
	mc
md
A::ma
*/
int main()
{
	D d;

	return 0;
}




#if 0
class Base // 虚基类
{
public:
	Base(int data = 10) :ma(data) { cout << "Base()" << endl; }
	~Base() { cout << "~Base()" << endl; }
private:
	int ma;
};
/*
vbptr(virtual base ptr) ------>  vbtable  0  8
mb
ma
*/

class Derive : virtual public Base // 虚继承
{
public:
	Derive(int data=20):Base(data), mb(data) { cout << "Derive()" << endl; }
	~Derive() { cout << "~Derive()" << endl; }
private:
	int mb;
};
int main()
{
	cout << sizeof(Derive) << endl;
	return 0;
}


class Base
{
public:
	Base(int a) :ma(a)
	{
		cout << "Base()" << endl;
	}
	~Base() { cout << "~Base()" << endl; }
	virtual void show() { cout << "Base::show()" << endl; }
protected:
	int ma;
};
class Derive : public Base
{
public:
	Derive(int data) :Base(data), mb(data)
	{
		cout << "Derive()" << endl;
	}
	~Derive() { cout << "~Derive()" << endl; }
	virtual void show() { cout << "Derive::show()" << endl; }
private:
	int mb;
};
int main()
{
	Derive *p = (Derive*)new Base(10);
	p->show();
	delete p;
	cout << typeid(*p).name() << endl;
	return 0;
}


// 基类 =》不代表任何实体 =》不用实例化对象 =》给派生类保留公共的覆盖接口(重写)和公共的属性(复用)
class Base
{
public:
	Base(int a) :ma(a)
	{
		cout << "Base()" << endl;
		clear();
	}
	~Base() { cout << "~Base()" << endl; }
	void clear() { memset(this, 0, sizeof(*this)); }
	virtual void show() { cout << "Base::show()" << endl; }
protected:
	int ma;
};
class Derive : public Base
{
public:
	Derive(int data) :Base(data), mb(data)
	{
		cout << "Derive()" << endl;
	}
	~Derive() { cout << "~Derive()" << endl; }
	virtual void show() { cout << "Derive::show()" << endl; }
private:
	int mb;
};
int main()
{
	//Base *p = new Base(0);
	//p->show();

	Base *p2 = new Derive(20);  // 问题1:这里为什么没挂掉
	p2->show();
	delete p2; //问题2:这里为什么不调用派生类的析构函数

	return 0;
}





class Base
{
public:  // &Base::~Base
	Base(int data) :pa(new int(data)) { cout << "Base()" << endl; }
	// 虚析构函数
	virtual ~Base() { cout << "~Base()" << endl; delete pa; }
private:
	int *pa;
};
class Derive : public Base
{
public:
	Derive(int data) :Base(data), pb(new int(data))
	{
		cout << "Derive()" << endl;
	}// &Derive::~Derive   
	~Derive() { cout << "~Derive()" << endl; delete pb; }
private:
	int *pb;
};
int main()
{
	//Derive d(20)
	Base *p = new Derive(10);
	delete p;  // eax, dword ptr[p]   ecx,dword ptr[eax]  call ecx
	
	return 0;
}



class Base
{
public:
	Base(int a) :ma(a) 
	{ 
		cout << "Base()" << endl; 
		clear();
	}
	~Base() { cout << "~Base()" << endl; }
	void clear() { memset(this, 0, sizeof(*this)); }
	virtual void show() { cout << "Base::show()" << endl; }
protected:
	int ma;
};
class Derive : public Base
{
public:
	Derive(int data) :Base(data), mb(data) 
	{
		cout << "Derive()" << endl; 
	}
	~Derive() { cout << "~Derive()" << endl; }
	virtual void show() { cout << "Derive::show()" << endl; }
private:
	int mb;
};
int main()
{
	//Base *p = new Base(0);
	//p->show();

	Base *p2 = new Derive(0);  // 问题1:这里为什么没挂掉
	p2->show();
	delete p2; //问题2:这里为什么不调用派生类的析构函数

	return 0;
}


class Animal // 有纯虚函数的类  =》  抽象类          >>>>>(多重继承)虚基类
{
public:
	Animal(string name) :_name(name) {}
	virtual void bark() = 0;// 纯虚函数
protected:
	string _name;
};

class Cat : public Animal
{
public:
	Cat(string name):Animal(name){}
	void bark() { cout << _name << " bark:喵喵!" << endl; }
};
class Dog : public Animal
{
public:
	Dog(string name) :Animal(name) {}
	void bark() { cout << _name << " bark:旺旺!" << endl; }
};
int main()
{
	Animal *p1 = new Cat("猫");
	Animal *p2 = new Dog("二哈");
	int *p11 = (int*)p1;
	int *p22 = (int*)p2;
	int tmp = p11[0];
	p11[0] = p22[0];
	p22[0] = tmp;
	p1->bark();
	p2->bark();
	cout << typeid(*p1).name() << endl;
	return 0;
}


class Window
{
public:
	Window(int t = 0) 
	{ a = t; cout << "window" << endl; }
	virtual void onResize() 
	{ a = 10;  cout << "call Window::onResize" << endl; }
	int a;
};

class SpecialWindow :public Window
{
public:
	virtual void onResize()
	{
		// (Test)50;
		((Window)(*this)).onResize();
		cout << "call SpecialWindow::onResize" << endl;
		cout << Window::a << endl;
	}
};
int main()
{
	SpecialWindow sw;  //  8  vfptr  a
	sw.onResize();

	return 0;
}

//老师,这段代码中,如果使用子类的对象调用onResize()函数,为什么a的值没有被改变呢?


class Base
{
public:
	Base(int a) :ma(a) { cout << "Base()" << endl; }
	~Base() { cout << "~Base()" << endl; }
	virtual void show() { cout << "Base::show()" << endl; }
	virtual void show(int i) { cout << "Base::show(int)" << endl; }
protected:
	int ma;
};
class Derive : public Base
{
public:
	Derive(int data) :Base(data), mb(data) { cout << "Derive()" << endl; }
	~Derive() { cout << "~Derive()" << endl; }
	virtual void show() { cout << "Derive::show()" << endl; }
private:
	int mb;
};
int main()
{
	Derive d(20);
	
	Base *pb = &d;
	pb->show(); //静态绑定 Base::show   call  Base::show (0E912DAh)
	/*
	动态绑定    vfptr vftable什么时候生成,运行时加载到哪块内存
	mov eax, dword ptr[pb]
	mov ecx, dword ptr[eax]
	call ecx
	*/
	cout << sizeof(Base) << endl;  // 4  8
	cout << sizeof(Derive) << endl; // 8  12

	// 识别的都是静态(编译时期)类型,显示识别的是RTTI run-time type infomation
	cout << typeid(pb).name() << endl;  // Base*  Base*
	cout << typeid(*pb).name() << endl; // Base   Derive

	return 0;
}
#endif

#if 0
class Base
{
public:
	Base(int a) :ma(a) { cout << "Base()" << endl; }
	~Base() { cout << "~Base()" << endl; }
	void show() { cout << "Base::show()" << endl; }
	void show(int i) { cout << "Base::show(int)" << endl; }
protected:
	int ma;
};
class Derive : public Base
{
public:
	Derive(int data) :Base(data), mb(data) { cout << "Derive()" << endl; }
	~Derive() { cout << "~Derive()" << endl; }
	void show() {cout << "Derive::show()" << endl;}
private:
	int mb;
};
int main()
{
	// 继承结构  从上到下的结构  
	Base b(10);
	Derive d(20);
	//a part of... xxx是xxx的一部分  组合 body  leg
	//a kind of... xxx是xxx的一种    继承 人Man  =  学生Student
	//d = b;  // 派生类对象 = 基类对象  no   上 =》 下
	b = d;  // 基类对象 = 派生类对象  yes  下 =》 上

	Base *pb = &d; // 基类指针/引用 = 派生类对象  yes   下 =》 上
	pb->show(10);

	//Derive *pd = &b; // 派生类指针/引用 = 基类对象 上 =》 下
	//pd->show();  // mb

	return 0;
}


class Base
{
public:
	Base(int a) :ma(a) { cout << "Base()" << endl; }
	~Base() { cout << "~Base()" << endl; }
	void show() { cout << "Base::show()" << endl; }
	void show(int i) { cout << "Base::show(int)" << endl; }
protected:
	int ma;
};
class Derive : public Base
{
public:
	//“Base”: 没有合适的默认构造函数可用
	Derive(int data) :Base(data), mb(data) { cout << "Derive()" << endl; }
	~Derive() { cout << "~Derive()" << endl; }
	void show() 
	{ 
		cout << "Derive::show()" << endl;
	}
private:
	int ma;
	int mb;
};
int main()
{
	Derive d(10);
	d.show(20); // “Derive::show”: 函数不接受 1 个参数
	d.show();
	d.Base::show();
	

	return 0;
}


// A是基类
class A
{
public:
	int ma;
protected:
	int mb;
private:
	int mc;
};
// B是派生类,继承到派生类里面的成员访问限定 <= 继承方式
class B : private A 
{
public:
	int md;
protected:
	int me;
private:
	int mf;
};
class C : public B
{
	// ma的访问限定是什么?
};

int main()
{
	B b;
	cout << b.mb << endl;

    std::cout << "Hello World!\n"; 
}
#endif

// 运行程序: Ctrl + F5 或调试 >“开始执行(不调试)”菜单
// 调试程序: F5 或调试 >“开始调试”菜单

// 入门提示: 
//   1. 使用解决方案资源管理器窗口添加/管理文件
//   2. 使用团队资源管理器窗口连接到源代码管理
//   3. 使用输出窗口查看生成输出和其他消息
//   4. 使用错误列表窗口查看错误
//   5. 转到“项目”>“添加新项”以创建新的代码文件,或转到“项目”>“添加现有项”以将现有代码文件添加到项目
//   6. 将来,若要再次打开此项目,请转到“文件”>“打开”>“项目”并选择 .sln 文件

2. C++结构

请添加图片描述

3.c++继承

请添加图片描述

4.c++总结

在这里插入图片描述

5.c++常见问题

#include<iostream>
using namespace std;
/*
重载,隐藏(),覆盖(虚函数)
虚函数(动态绑定,在运行时绑定)
在编译阶段产生虚函数表;存放虚函数的地址,在.rodata段存放
对象多一个虚函数指针,
虚函数多少不影响对象的大小,只影响虚函数表,函数表与类型对应

派生类继承的基类的虚函数后自己也是虚函数,隐藏的作用域,覆盖虚函数表,
大小(vfptr,加对象),
两个vfptr指向派生类的虚函数表
多态:
静态(编译运行)的多态:函数模板和模板,

动态(运行阶段)的多态:虚函数
基类指针调用同名覆盖方法


9.常见问题实例:析构函数可以实现为虚函数
能不能成为虚函数:====》记录虚函数地址,找到虚函数指针(在对象的前四个字节),要有还要能取地址
1.构造函数不可以为虚函数,在构造之前没有对象
在构造函数中在调用virutal函数,请问是动态还是静态???是静态绑定,未产生对象,没有对象的前四个字节,先初始化基类的构造函数,
在析构函数中调用virutal函数,请问是动态还是静态??==》动态,可以,对象是在的
virual static void fun()不可以,因为不需要对象,没有虚函数表
virual inline void fun()内联函数,可以,
2.什么时候析构函数必须写为虚析构函数,???
基类指针指向或引用堆上派生类的对象时,

10.调用虚函数一定会发生动态绑定吗?哈哈哈
汇编  call +函数名   ==》静态绑定
call  寄存器===》动态绑定
对象调用虚函数,永远是静态绑定
指针,引用,调用虚函数发生动态绑定 ,
不能用派生类指针指向基类对象,
单一继承
多重继承:
1.有什么坏处???
答:继承的基类数据可能有多份
2.虚基类是什么
被虚继承的那个类,
在考虑继承类的内存布局时,先不考虑虚继承,然后再把虚基类的地方改为vbptr表,
里面存放的是到此继承类数据的偏移量
3.vbptr(虚基类指针)向上向偏移量,vdptr,
空类大小是1个字节;
C++的四种类型强制转换
:
const_cast
const int a=10;
int *p =(int *)&a;
int *pconst_cast<int *>(&a);
static_cast;
reinterpret_cast<==>(Type)
dynamic_cast;识别RRTTI类型的转换
STL六大
顺序,关联,迭代器,泛型算法,函数对象

*/

/*  


*/
int main()
{
	return 0;

}
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

我的sun&shine

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值