补充:
1. 析构函数:
1.1 派生类指针操作派生类对象,基类析构函数不是虚函数,此时会先释放派生类的资源,再释放基类的资源,这里资源就不会出现泄漏的情况。
1.2 基类指针操作派生类对象,基类析构函数不是虚函数:此时只是释放了基类的资源,而没有调用派生类的析构函数,这样的删除只能够删除基类对象,而不能删除子类对象,形成了删除一半对象,造成内存泄漏。
1.3 基类指针操作派生类对象,基类析构函数是虚函数:此时释放了派生类的资源,再调用基类的析构函数。
在公有继承中,基类对派生类及其对象的操作,只能影响到那些从基类继承下来的成员。如果想要用基类对非继承成员进行操作,则要把基类的这个函数定义为虚函数。
析构函数自然也应该如此:如果它想析构子类中的重新定义或新的成员及对象,当然也应该声明为虚的。
如果不需要基类对派生类及对象进行操作,则不能定义虚函数,因为这样会增加内存开销.当类里面有定义虚函数的时候,编译器会给类添加一个虚函数表,里面来存放虚函数指针,这样就会增加类的存储空间。所以,只有当一个类被用来作为基类的时候,并且有使用到基类指针操作派生类的情况时,才把析构函数写成虚函数。
-------------------------------------------补充--完------------------------------------------------
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. 纯虚函数和抽象类