继承易错总结

继承会将所有的成员继承下来,但是继承方式限定的是继承下来成员的可见类型(如果是private继承,那么他不论哪里都是不可见的;如果是protected继承在类中是可见的,在类外是不可见的;如果是public继承,在任何地方都是可见的)

虚函数类外定义时,不必加virtual

编译时多态——静态多态——模板和重载
运行时多态——动态多态——虚函数

友元函数 构造函数 static静态函数 不能用virtual关键字修饰;
普通成员函数 和析构函数 可以用virtual关键字修饰;

对于静态成员变量,不计入字节大小
静态成员变量类内声明类外初始化
静态成员函数为什么不能设置为虚函数:
静态成员函数不属于任何成员,属于整个类,不能使用this来访问
virtual构成的虚函数,恰恰是使用this指针访问,this->vfptr-> 虚函数地址
静态成员函数没有this指针,实现多态就是需要不同的对象,调用不同的子类进行访问不同的重写函数

final和override
final修饰的类——这个类不能被继承
override修饰子类继承父类的虚函数——强制检查这个虚函数是不是重写父类的虚函数,编译的时候报错,提高编程效率
重写的虚函数必须加上override并且要去掉virtual,virtual只能在最上层加(不是语法,而是代码规范)

class A
{
  static int _tem;//静态成员变量类内声明,类外初始化
};

int A::_tem = 0;//在类外初始化的时候不加static

静态成员变量会继承使用权,但是不能被包含
静态成员变量不存储在类中,计算类的大小的时候不计算他的字节大小

重载:同一个作用域中,函数名相同,参数类型不同,参数数量不同,参数顺序不同
重定义(隐藏):继承中,函数名相同(可使用作用域进行访问)
重写(覆盖):继承的虚函数中,子类重写父类的虚函数

派生类的构造函数,不写会调用默认的构造函数,但是如果自己写,就要自己调用父类的构造函数(在调用父类的构造函数时,要将父类当成一个整体)

class Base
{
public:
	Base()
	{
		puts("Base()");
	}
	Base(int a):_a(a)
	{
		puts("Base(int a)");
	}
	Base(const Base& tem)
	{
		puts("Base(const Base& tem)");
	}
	Base& operator=(const Base& tem)
	{
		puts("Base& operator=(const Base& tem)");
		_a = tem._a;
		return *this;
	}
	~Base()
	{
		puts("Base");
	}
private:
	int _a;
};
class Son:public Base
{
public:
	Son()
	{
		puts("Son()");
	}
	Son(int a, int b)
		:Base(a),_b(b)
	{
		puts("Son(int a,int b)");
	}
	Son(const Son& tem)
		:Base(tem)
	{
		//父类接受子类的对象/引用/指针
		puts("Son(const Son& tem)");
	}
	Son& operator=(const Son& tem)
	{
		puts("Son& operator=(const Son& tem)");
		Base::operator=(tem);
		return *this;
	}
	~Son()
	{
		//在析构函数的时候,可以不手动调用析构函数
		//编译器会自动调用父类的析构函数
		puts("~Son()");
	}
private:
	int _b;
};

inline能不能是虚函数:可以(内敛函数没有地址)
多态调用:内敛不起作用(多态调用中,虚函数存在虚函数表中,需要地址,但是内联函数没有地址,所以内敛不起作用)
普通调用:内敛起作用

构造函数能不能是虚函数?不能
虚表是在编译时生成,构造的时候进行初始化
如果构造函数是虚函数,那么在实例化对象的时候,如何应该去虚表中找构造函数的地址,但是这时候虚表还没有初始化

多态调用和普通函数的时间效率?
具体要看是否构成多态,调用需要到需表中找地址进行调用,普通成员函数可以直接调用

多态的本质——虚表
当父类的指针/引用接收子类的地址/对象时,因为是继承会进行切割,将子类的父类那部分切出来,剩下的就是去虚表中找地址进行调用就行了

父类=子类;会将父类的那部分切出来拷贝给父类,但是不会拷贝虚函数表指针
虚函数指针如果进行了拷贝,那么父类对象的虚函数表指针会发生改变,当使用父类对象调用父类的虚函数时,就会发生错误

虚函数继承,继承的是接口,参数类型不会改变;当子类对象要调用父类的函数时,使用切片的手法进行调用
普通函数继承,继承的是实现


子类和父类都有虚函数,子类的虚函数会存到哪里
继承易错总结_第1张图片

从右表中可以看到,应该是有三个虚函数,他们在同一个虚表中
子类中没有虚表,子类的虚函数存到父类的虚表中

继承易错总结_第2张图片

可以记成向上合并

你可能感兴趣的:(java,开发语言)