一:纯虚函数和抽象类
纯虚函数是一个在基类中说明的虚函数,在基类中没有定义,要求任何派生类都定义自己的版本
纯虚函数为各个派生类提供一个公共接口
纯虚函数的形式:
virtual 类型 函数名(参数列表)=0;
一个具有纯虚函数的基类称为抽象类
注意:抽象类不能实例化对象
一个派生类继承抽象类但是未实现纯虚函数,则也变为抽象类,可以继续被继承实现
class Parent
//抽象类
{
public:
Parent()
{
cout <<
"Parent construct" <<
endl;
}
virtual void overrideFunc() = 0; //纯虚函数
};
class Child01:public Parent //未实现纯虚函数,所以还是一个抽象类,不能被实例化对象,可以被继承
{
public:
Child01()
{
cout <<
"Child01 construct" <<
endl;
}
};
class Child02 :public Parent //未实现纯虚函数,是抽象类,可以被继承实现
{
public:
Child02()
{
cout <<
"Child02 construct" <<
endl;
}
};
class ChildSon :
public Child01
{
public:
ChildSon()
{
cout <<
"ChildSon construct" <<
endl;
}
virtual void overrideFunc() //实现了纯虚函数,是一个可以实例化对象的类
{
cout <<
"ChildSon finish" <<
endl;
}
};
void main()
{
ChildSon c;
system("pause");
}
二:虚析构函数
(0)注意:构造函数不能是虚函数:建立一个派生类对象时,必须从类层次的根开始,沿着继承路径逐个调用基类的构造函数
(一)问题引出:未使用虚析构函数时会出现内存泄漏(当父类指针指向子类对象时)
class Parent
//抽象类
{
public:
char *
name;
public:
Parent(char*
n)
{
name = (
char *)malloc(strlen(n) +
1);
strcpy(name, n);
cout <<
"Parent construct" <<
endl;
}
virtual void getInfo()
{
cout <<
"parent name:" <<
this->name <<
endl;
}
~
Parent()
{
cout <<
"Parent distruct" <<
endl;
if (
this->
name)
{
delete this->
name;
this->name =
NULL;
}
}
};
class Child01:
public Parent
{
public:
char *
addr;
public:
Child01(char* n,
char*
a) :Parent(n)
{
addr = (
char *)malloc(strlen(a) +
1);
strcpy(addr, a);
cout <<
"Child01 construct" <<
endl;
}
virtual void getInfo()
{
cout <<
"child01 name:" <<
this->name <<
endl;
cout <<
"child01 addr:" <<
this->addr <<
endl;
}
~
Child01()
{
cout <<
"Child01 distruct" <<
endl;
if (
this->
name)
{
delete name;
this->name = NULL;
//释放后置空,是一个良好的习惯
}
if (
this->
addr)
{
delete addr;
this->addr =
NULL;
}
}
};
void main()
{
Parent* p = new Child01("Liu","zz");
delete p; //会根据父类指针去调用父类析构函数:回顾前面多态
system("pause");
}
发现只调用了父类析构函数,释放了name变量,但是addr变量并没有进行释放,导致了内存泄漏
(二)问题解决:联系前面多态,使用虚析构函数--->会根据虚函数指针找到虚函数表从而调用子类析构函数(而)子类析构时候同构造相反方向去调用基类析构方法《重点》
class Parent
//抽象类
{
public:
char *
name;
public:
Parent(char*
n)
{
name = (
char *)malloc(strlen(n) +
1);
strcpy(name, n);
cout <<
"Parent construct" <<
endl;
}
virtual void getInfo()
{
cout <<
"parent name:" <<
this->name <<
endl;
}
virtual ~
Parent()
{
cout <<
"Parent distruct" <<
endl;
if (
this->
name)
{
delete this->
name;
this->name =
NULL;
}
}
};
class Child01:
public Parent
{
public:
char *
addr;
public:
Child01(char* n,
char*
a) :Parent(n)
{
addr = (
char *)malloc(strlen(a) +
1);
strcpy(addr, a);
cout <<
"Child01 construct" <<
endl;
}
virtual void getInfo()
{
cout <<
"child01 name:" <<
this->name <<
endl;
cout <<
"child01 addr:" <<
this->addr <<
endl;
}
virtual ~
Child01()
{
cout <<
"Child01 distruct" <<
endl;
if (
this->
name)
{
delete name;
this->name = NULL;
//释放后置空,是一个良好的习惯
}
if (
this->
addr)
{
delete addr;
this->addr =
NULL;
}
}
};
void testfunc()
{
Parent* p =
new Child01(
"Liu",
"zz");
delete p;
}
void main()
{
testfunc();
system("pause");
}
三:回顾delete运算符
(一)注意:在C中使用malloc和free函数来分配和释放内存,在C++中扩展了new和delete运算符
(二)其中new和delete运算符使用:
new运算符的使用:
指针变量 =
new 类型(常数);
指针变量 =
new 类型[表达式];
delete运算符的使用:
delete 指针变量
delete []指针变量
(三)重点:delete中使用的指针变量必须是一个new返回的指针变量《重点》
正确使用:
Parent* p =
new Child01(
"Liu",
"zz");
delete p;
错误使用:
Child01 c(
"Liu",
"zz");
Parent* p = &
c;
delete p;
转载于:https://www.cnblogs.com/ssyfj/p/10777237.html