C++知识点集锦(类中的多态、虚函数、vtable、vptr、static对象等)

C++三大特性

封装、继承、多态

封装

封装可以隐藏实现细节,使得代码模块化
封装是把过程和数据包围起来,对数据的访问只能通过已定义的界面。

数据抽象

只向外界提供关键信息,并隐藏其后台的实现细节,即只表现必要的信息而不呈现细节。

抽象类

类中至少有一个函数被声明为纯虚函数/纯虚函数是通过在声明中使用=0来指定。
抽象类不能被实例化。

多态

多态指的是父类类型的指针指向其子类对象,可以调用子类仲被重写的方法

动态联编、静态联编

动态联编: 在运行的时候,自动判断指向的成员函数
静态联编:在编译阶段,确定指向的成员函数是指针类型的成员函数

虚函数

虚函数的定义要遵循以下重要规则:

1.如果虚函数在基类与派生类中出现,仅仅是名字相同,而形式参数不同,或者是返回类型不同,那么即使加上了virtual关键字,也是不会进行滞后联编的。

2.只有类的成员函数才能说明为虚函数,因为虚函数仅适合用与有继承关系的类对象,所以普通函数不能说明为虚函数。

3.静态成员函数不能是虚函数,因为静态成员函数的特点是不受限制于某个对象。

4.内联(inline)函数不能是虚函数,因为内联函数不能在运行中动态确定位置。即使虚函数在类的内部定义定义,但是在编译的时候系统仍然将它看做是非内联的。

5.构造函数不能是虚函数,因为构造的时候,对象还是一片位定型的空间,只有构造完成后,对象才是具体类的实例。

6.析构函数可以是虚函数,而且通常声名为虚函数。

static类数据成员/成员函数

两者都不能用this指针指向他们

  • 类数据成员
    static类数据成员独立于一切类对象存在。
    static不会像普通类数据成员一样每一个类对象都有一份,全部类对象是共享一个static类成员的。
    static类对象必须要在类外进行初始化
class Text{
	public:
	static int count;
} ;
int Text::count=0; //必须初始化
  • 类成员函数
    类成员函数里不能访问非static类成员

虚函数表vtable以及vptr

如果一个类包含了虚函数,那么在创建对象时会额外增加一张表,表中的每一项都是虚函数的入口地址,虚函数按照创建的优先顺序排列。这张表就是虚函数表,也称为 vtable。
可以认为虚函数表是一个数组。 为了把对象和虚函数表关联起来,编译器会在对象中安插一个指针vptr(在对象对应的内存空间的开头),指向虚函数表的起始位置。
例子:

class A{
protected:
	int a1;
	int a2;
public:
	virtual void display(){
		cout<<"A::display()"<<endl;
	}
	virtual void clone(){ 
		cout<<"A::clone()"<<endl;
	};
};

class B: public A{
protected:
	int b;
public:
	virtual void display(){
		cout<<"B::display()"<<endl;
	}
	virtual void init(){ 
		cout<<"B::init()"<<endl;
	}
};

class C: public B{
protected:
	int c;
	
public:
	virtual void display(){
	cout<<"C::display()"<<endl;
	}
	virtual void execute(){ 
	cout<<"C::execute()"<<endl;
	}
};

各个类的内存分布如下所示:
虚函数表

猜你喜欢

转载自blog.csdn.net/crabstew/article/details/88719544