补充:

1. 析构函数:

1.1 派生类指针操作派生类对象,基类析构函数不是虚函数,此时会先释放派生类的资源,再释放基类的资源,这里资源就不会出现泄漏的情况。

1.2 基类指针操作派生类对象,基类析构函数不是虚函数:此时只是释放了基类的资源,而没有调用派生类的析构函数,这样的删除只能够删除基类对象,而不能删除子类对象,形成了删除一半对象,造成内存泄漏。

1.3 基类指针操作派生类对象,基类析构函数是虚函数:此时释放了派生类的资源,再调用基类的析构函数。

C++中析构函数为虚函数

        在公有继承中,基类对派生类及其对象的操作,只能影响到那些从基类继承下来的成员。如果想要用基类对非继承成员进行操作,则要把基类的这个函数定义为虚函数。

        析构函数自然也应该如此:如果它想析构子类中的重新定义或新的成员及对象,当然也应该声明为虚的。

       如果不需要基类对派生类及对象进行操作,则不能定义虚函数,因为这样会增加内存开销.当类里面有定义虚函数的时候,编译器会给类添加一个虚函数表,里面来存放虚函数指针,这样就会增加类的存储空间。所以,只有当一个类被用来作为基类的时候,并且有使用到基类指针操作派生类的情况时,才把析构函数写成虚函数。

 

 

-------------------------------------------补充--完------------------------------------------------

1. 函数模板不会被编译,不能直接被使用,所以函数模板必须实例化(参数赋予实数、类型)

    由函数模板实例化出来的函数叫模板函数

 

//可以通过运算符重载进行比较

 

函数模板
template <class T>
/*T max(T x, T y)
{
	return x > y ? x : y;
}*/
int max(int a, int b)
{
	return a > b ? a : b;
}

int main()
{
	int num1 = 1;
	int num2 = 2;
	char ch1 = 3;
	char ch2 = 4;
	cout << "max(num1, num2): " << max(num1, num2) << endl; //调用max(int,int)

	//
	cout << "max(ch1, ch2): " << max(ch1, ch2) << endl; //此行输出max(num1, num2): 2    max(ch1, ch2) : (乱码)

	//类型转换后调用max(int,int),注释掉函数模板后,不能匹配参数类型max(int,char),
	//那么调用的是那个模板??
	//cout << "max(num1, ch1): " << max(num1, ch1) << endl;  

	cout << endl;
	return 0;
}

2. 双向链表插入

2.1 类模板改造双向链表

类模板实现双向链表
template<class T> //类模板
class node
{
	T value;
	node* prev, * next;
public:
	node() :prev(nullptr), next(nullptr) {}
	void setValue(T value) { this->value = value; }
	void append(node* p);
};
template<class T>  //在类外定义要加上template以及模板形参列表;此处为声明,要加class
void node<T>::append(node* p)  //此处为使用,不用加class; node<T>是类模板的名字
{
	p->next = this->next;
	p->prev = this->prev;
	if (next != nullptr)
	{
		next->prev = p;
	}
	next = p;
}


int main()
{
	node<int>* list_head; //用模板实参实例化模板类
	node<int> node, node1, node2;
	node.setValue(1);
	node1.setValue(2);
	node2.setValue(3);
	list_head = &node;
	list_head->append(&node1);
	list_head->append(&node2);



	cout << endl;
	return 0;
}

//注意:

3. 命名空间

4.1 使用方法

4.2 using namespace ;

5. 异常处理

5.1 try / catch语句

5.2 if/else 方式

5.3 throw方式

示例1

示例2    :f3接收double类型,会捕获两次

示例3   f3的catch在cout<<"OK3!"<<endl;后直接throw给上层,输出end3不执行

6. 异常的类型

7. 虚函数

示例

//基类和派生类重名成员,默认调用派生类的成员

用函数重载改进(静态多态)

//错误示例

//示例的虚函数形式,运行时的多态

//上图原理

//只有在 public 派生中才可以如此

//示例

点击查看代码
class Base
{
public:
	void Print()
	{
		cout << "I am Base\n";
	}

};
class Drived:public Base
{
public:
	void Print()
	{
		cout << "It is Drived!\n";
	}
};




int main()
{
	Base base, * p;
	Drived drived;
	p = &base;
	p->Print();

	p = &drived;
	p->Print();



	cout << endl;
	return 0;
}

/*output
I am Base
I am Base
*/

点击查看代码
class Base
{
public:
	virtual void Print()
	{
		cout << "I am Base\n";
	}

};
/*output
I am Base
It is Drived!
*/
点击查看代码
class Base
{
public:
	virtual void Print()
	{
		cout << "I am Base\n";
	}

};
class Derived1:public Base
{
public:
	void Print()
	{
		cout << "It is Derived1!\n";
	}
};
class Derived2 :public Base
{
public:
	void Print()
	{
		cout << "This is Derived2!\n";
	}
};




int main()
{
	Base base, * p;
	Derived1 derived1;
	Derived2 derived2;
	
	p = &base;
	p->Print();

	p = &derived1;
	p->Print();

	p = &derived2;
	p->Print();



	cout << endl;
	return 0;
}
/*output
I am Base
It is Derived1!
This is Derived2!
*/

//当不通过引用或指针时

不通过引用或指针,通过值传递
class Base
{
public:
	virtual void Print()
	{
		cout << "I am Base\n";
	}

};
class Derived1:public Base
{
public:
	void Print()
	{
		cout << "It is Derived1!\n";
	}
};
class Derived2 :public Base
{
public:
	void Print()
	{
		cout << "This is Derived2!\n";
	}
};




int main()
{
	Base base, p;
	Derived1 derived1;
	Derived2 derived2;
	
	p = base;
	p.Print();

	p = derived1;
	p.Print();

	p = derived2;
	p.Print();



	cout << endl;
	return 0;
}
/*output
I am Base
I am Base
I am Base
*/

7.x 虚函数的动态绑定,运行时多态

7.x 虚函数意义

基类指针操作派生类对象,基类析构函数是虚函数
class Base
{
public:
	virtual ~Base()
	{
		cout << "Base destroy\n";
	}

};
class Derived:public Base
{
public:
	~Derived()
	{
		cout << "Derived destroy\n";
	}
};

int main()
{
	Base* p1, * p2;
	p1 = new Base();
	p2 = new Derived();
	delete p1;
	delete p2;

	cout << endl;
	return 0;
}

/*output
Base destroy
Derived destroy
Base destroy
*/
基类指针操作派生类对象,基类析构函数不是虚函数
#include<iostream>
using namespace std;
class ClxBase{
public:
	ClxBase() {};
	~ClxBase() { cout << "Output from the destructor of class ClxBase!" << endl; };
 
	void DoSomething() { cout << "Do something in class ClxBase!" << endl; };
};
 
class ClxDerived : public ClxBase{
public:
	ClxDerived() {};
	~ClxDerived() { cout << "Output from the destructor of class ClxDerived!" << endl; };
 
	void DoSomething() { cout << "Do something in class ClxDerived!" << endl; };
};
int main(){
	ClxBase *p = new ClxDerived;		// 基类指针操作派生类对象
	p->DoSomething();
	delete p;
	system("pause");
	return 0;
}
/*output
Do something in class ClxBase!
Output from the destructor of class ClxBase!
*/
派生类指针操作派生类对象,基类析构函数不是虚函数
#include<iostream>
using namespace std;
class ClxBase{
public:
	ClxBase() {};
	~ClxBase() { cout << "Output from the destructor of class ClxBase!" << endl; };
 
	void DoSomething() { cout << "Do something in class ClxBase!" << endl; };
};
 
class ClxDerived : public ClxBase{
public:
	ClxDerived() {};
	~ClxDerived() { cout << "Output from the destructor of class ClxDerived!" << endl; };
 
	void DoSomething() { cout << "Do something in class ClxDerived!" << endl; };
};
int main(){
    ClxDerived *p = new ClxDerived;		// 派生类指针操作派生类对象
	p->DoSomething();
	delete p;
	system("pause");
	return 0;
}
/*
Do something in class ClxDerived!
Output from the destructor of class ClxDerived!
Output from the destructor of class ClxBase!
*/

8. 纯虚函数和抽象类