C++基础16-类和对象之联编,重写,虚析构

1、静态联编和动态联编

1、联编是指一个程序模块、代码之间互相关联的过程。

2、静态联编(sta5c binding),是程序的匹配、连接在编译阶段实现,也称为早期匹配。重载函数使用静态联编。

3、动态联编是指程序联编推迟到运行时进行,所以又称为晚期联编(迟绑定)。switch 语句 if 语句多态是动态联编的例子。

说明:

1C++C相同,是静态编译型语言

2、在编译时,编译器自动根据指针的类型判断指向的是一个什么样的对象;所以编译器认为父类指针指向的是父类对象。

3、由于程序没有运行,所以不可能知道父类指针指向的具体是父类对象还是子类对象从程序安全的角度,编译器假设父类指针只指向父类对象,因此编 译的结果为调用父类的成员函数。这种特性就是静态联编。

4、多态的发生是动态联编,实在程序执行的时候判断具体父类指针应该调用的方法。

//A.动态联编的基础是虚函数
//B.动态联编时在运行时确定所调用的函数代码
//C.只有通过基类的指针或引用才能实现动态联编

2、虚析构函数

构造函数不能是虚函数。建立一个派生类对象时,必须从类层次的根开始,沿着继承路径逐个调用基类的构造函数。

析构函数可以是虚的虚析构函数用于指引 delete 运算符正确析构动态 对象

    通常用于父类指针指向子类对象时,释放父类指针时会默认调用父类析构函数,而不会调用子类的析构函数,可能会造成内存泄漏。当把父类的析构函数定义为虚函数时,当释放父类指针时就会发生多态,先调用子类析构函数,再调用父类构造函数

3、重载、重写、重定义

重载(添加):

         a 相同的范围(在同一个类中)

         b 函数名字相同

         c 参数不同 (个数或类型)

         d virtual关键字可有可无

重写(覆盖) 是指派生类函数覆盖基类函数,特征是:

        a 不同的范围,分别位于基类和派生类中

        b 函数的名字相同

        c 参数相同

        d 基类函数必须有virtual关键字

重定义(隐藏) 是指派生类的函数屏蔽了与其同名的基类函数,规则如下:

       a 如果派生类的函数和基类的函数同名,但是参数不同,此时,不管有无virtual,基类的函数被隐藏。

       b 如果派生类的函数与基类的函数同名,并且参数也相同,但是基类函数没有vitual关键字,此时,基类的函数被隐藏。

即:重载:同一个作用域下(形参个数不同,类型不同)
       重写:如果父类是虚函数,子类在定义一遍。则为重写(虚函数重写)
       重定义:发生在两个不同的类中。一个是父类 一个是子类。 //父类普通函数,子类重新写了一遍(普通函数定义)
           即:1、普通函数重定义  如果父类的普通成员函数,被子类重写。说是重定义
                  2、虚函数重写 如果父类的虚函数,被子类重写,就是虚函数重写。这个函数会发生多态

虚析构函数代码示例:
 

#if 1
#define _CRT_SECURE_NO_WARNINGS
#include<iostream>
using namespace std;
#if 0
class A {
public:
	A() {
		cout << "A() " << endl;
		this->p = new char[64];
		//memset(this->p, 0, 64);
		strcpy(this->p, "A String...");
	}
	virtual void print() {
		cout << "A的print函数" << this->p << endl;
	}
	~A() {
		cout << "~A()" << endl;
		if (this->p != NULL) {
			delete this->p;
			this->p = NULL;
		}
	}
private:
	char *p;
};
class B :public A {
public:
	B() {  //会触发A的构造函数
		cout << "B() " << endl;
		this->p = new char[64];
		//memset(this->p, 0, 64);
		strcpy(this->p, "B String...");
	}
	virtual void print() {
		cout << "B的print函数" << this->p << endl;
	}
	~B() {
		cout << "~B()" << endl;
		if (this->p != NULL) {  //默认是B的p
			delete this->p;
			this->p = NULL;
		}
	}
private:
	char* p;
};
void func(A *p) {
	p->print();
}
void test01() {
	A a; 
	func(&a);
	cout << "------" << endl;
	B b;
	func(&b);
}
/*
A()
A的print函数A String...
------
A()
B()
B的print函数B String...
~B()
~A()
~A()
*/
void test02() {
	B *bp = new B;
	func(bp);
	delete bp;
}
/*
A()
B()
B的print函数B String...
~B()
~A()
*/
void func2(A *p) {
	p->print();  //发生多态
	delete p;    //也应该发生多态
				 //此刻触发p默认的析构函数
				 //应该是触发谁 调用谁的析构函数 多态
}
void test03() {
	A *ap = new A;
	func2(ap);
}
/*
A()
A的print函数A String...
*/
void test04() {
	B *bp = new B;
	func2(bp);
}
/*
A()
B()
B的print函数B String...
~A()
*/
#endif
//在上面的基础上,将A的析构函数改为虚函数
class A {
public:
	A() {
		cout << "A() " << endl;
		this->p = new char[64];
		//memset(this->p, 0, 64);
		strcpy(this->p, "A String...");
	}
	virtual void print() {
		cout << "A的print函数" << this->p << endl;
	}
	virtual ~A() {
		cout << "~A()" << endl;
		if (this->p != NULL) {
			delete this->p;
			this->p = NULL;
		}
	}
private:
	char *p;
};
class B :public A {
public:
	B() {  //会触发A的构造函数
		cout << "B() " << endl;
		this->p = new char[64];
		//memset(this->p, 0, 64);
		strcpy(this->p, "B String...");
	}
	virtual void print() {
		cout << "B的print函数" << this->p << endl;
	}
	virtual ~B() {
		cout << "~B()" << endl;
		if (this->p != NULL) {  //默认是B的p
			delete this->p;
			this->p = NULL;
		}
	}
private:
	char* p;
};
void func2(A *p) {
	p->print();
	delete p;    //此刻触发p默认的析构函数
				 //应该是触发谁 调用谁的析构函数 多态
}
void test05() {
	B *bp = new B;
	func2(bp);
}
/*
A()
B()
B的print函数B String...
~B()
~A()
*/
int main() {
	//test01();
	//test02();
	//test03();
	//test04();
	test05();
	return 0;
}

//重载:同一个作用域下(形参个数不同,类型不同)
//重写:如果父类是虚函数,子类在定义一遍。则为重写(虚函数重写)
//重定义:发生在两个不同的类中。一个是父类 一个是子类。
         //父类普通函数,子类重新写了一遍(普通函数定义)
//即:1、普通函数重定义  如果父类的普通成员函数,被子类重写。说是重定义
//    2、虚函数重写 如果父类的虚函数,被子类重写,就是虚函数重写。这个函数会发生多态


//A.动态联编的基础是虚函数
//B.动态联编时在运行时确定所调用的函数代码
//C.只有通过基类的指针或引用才能实现动态联编
#endif

 

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

打赏作者

chde2Wang

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

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

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

打赏作者

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

抵扣说明:

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

余额充值