第七层:多态(下)

简介: 第七层:多态(下)

验证子类不重写函数也将变成抽象类:


#include<string>
#include<iostream>
using namespace std;
class drink
{
public:
  virtual void dele() = 0;
};
class mike :public drink
{
public:
  void dele(int a)
  {
  cout << "牛奶来咯" << endl;
  }
};
class orange :public drink
{
public:
  void dele()
  {
  cout << "橙汁来咯" << endl;
  }
};
class coke :public drink
{
public:
  void dele()
  {
  cout << "可乐来咯" << endl;
  }
};
void test1()
{
  mike d;
}
int main()
{
  test1();
  return 0;
}


虚析构和纯虚析构


在使用多态的时候,子类中有成员属性开辟空间到堆区,则父类指针在释放的时候无法调用子类中的析构函数

验证:


#include<string>
#include<iostream>
using namespace std;
//人
class people
{
public:
  people()//查看是否调用
  {
  cout << "父类内构造函数调用" << endl;
  }
  ~people()//查看是否调用
  {
  cout << "父类内析构函数调用" << endl;
  }
  virtual void come() = 0;//纯虚函数
};
//男人
class man :public people
{
public:
  man(string _name)//查看是否调用
  {
  cout << "子类内构造函数调用" << endl;
  this->_name = new string(_name);//对名字进行初始化
  }
  ~man()//查看是否调用
  {
  if (_name != NULL)
  {
    cout << "子类内析构函数调用" << endl;
    delete _name;
    _name = NULL;
  }
  }
  void come()
  {
  cout <<*_name<<"来咯" << endl;
  }
  string* _name;//用指针来管理名字
};
void test1()
{
  people* p = new man("张三");
  p->come();
  delete p;
  p = NULL;
}
int main()
{
  test1();
  return 0;
}

0eacb84100b54626af849e6b562bf92a.png

那这个时候就会造成内存泄漏,那怎么去解决呢?


将父类中的析构函数变成虚析构或者纯虚析构

#include<string>
#include<iostream>
using namespace std;
//人
class people
{
public:
  people()//查看是否调用
  {
  cout << "父类内构造函数调用" << endl;
  }
  virtual ~people()//查看是否调用
  {
  cout << "父类内析构函数调用" << endl;
  }
  virtual void come() = 0;//纯虚函数
};
//男人
class man :public people
{
public:
  man(string _name)//查看是否调用
  {
  cout << "子类内构造函数调用" << endl;
  this->_name = new string(_name);//对名字进行初始化
  }
  ~man()//查看是否调用
  {
  if (_name != NULL)
  {
    cout << "子类内析构函数调用" << endl;
    delete _name;
    _name = NULL;
  }
  }
  void come()
  {
  cout <<*_name<<"来咯" << endl;
  }
  string* _name;//用指针来管理名字
};
void test1()
{
  people* p = new man("张三");
  p->come();
  delete p;
  p = NULL;
}
int main()
{
  test1();
  return 0;
}

2d65d23f6d4748949b924e4057485923.png

选择就会走子类的调用,如果是纯虚析构呢?


#include<string>
#include<iostream>
using namespace std;
//人
class people
{
public:
  people()//查看是否调用
  {
  cout << "父类内构造函数调用" << endl;
  }
  virtual ~people() = 0;//查看是否调用
  virtual void come() = 0;//纯虚函数
};
//男人
class man :public people
{
public:
  man(string _name)//查看是否调用
  {
  cout << "子类内构造函数调用" << endl;
  this->_name = new string(_name);//对名字进行初始化
  }
  ~man()//查看是否调用
  {
  if (_name != NULL)
  {
    cout << "子类内析构函数调用" << endl;
    delete _name;
    _name = NULL;
  }
  }
  void come()
  {
  cout <<*_name<<"来咯" << endl;
  }
  string* _name;//用指针来管理名字
};
void test1()
{
  people* p = new man("张三");
  p->come();
  delete p;
  p = NULL;
}
int main()
{
  test1();
  return 0;
}

2e9b90b2ca334476abebe75bafe6eeaa.png

那这里是为什么呢?可以看到报错内容说纯虚析构是无法解析的外部符号,对比上面的虚析构,发现,纯虚析构没有定义,纯虚函数可以不用定义,那为什么纯虚析构就需要定义了呢?这是因为,析构是所有类在销毁前会走的一个函数,这个时候,内部没有实现,就走不过去,就会产生报错,那解决方法就是,在类外定义析构函数,需要在析构函数名前加上作用域:


#include<string>
#include<iostream>
using namespace std;
//人
class people
{
public:
  people()//查看是否调用
  {
  cout << "父类内构造函数调用" << endl;
  }
  virtual ~people() = 0;//查看是否调用
  virtual void come() = 0;//纯虚函数
};
people::~people()
{
  cout << "父类内析构函数调用" << endl;
}
//男人
class man :public people
{
public:
  man(string _name)//查看是否调用
  {
  cout << "子类内构造函数调用" << endl;
  this->_name = new string(_name);//对名字进行初始化
  }
  ~man()//查看是否调用
  {
  if (_name != NULL)
  {
    cout << "子类内析构函数调用" << endl;
    delete _name;
    _name = NULL;
  }
  }
  void come()
  {
  cout <<*_name<<"来咯" << endl;
  }
  string* _name;//用指针来管理名字
};
void test1()
{
  people* p = new man("张三");
  p->come();
  delete p;
  p = NULL;
}
int main()
{
  test1();
  return 0;
}

4cebaac233b3433da32a72337a77fc60.png


虚析构和纯虚析构的共性


可以解决父类指针释放子类对象

都需要有具体的函数实现


虚析构和纯虚析构的区别


有纯虚析构的类也是抽象类,无法实例化对象

验证:


#include<string>
#include<iostream>
using namespace std;
//人
class people
{
public:
  people()//查看是否调用
  {
  cout << "父类内构造函数调用" << endl;
  }
  virtual ~people() = 0;//查看是否调用
  virtual void come() = 0;//纯虚函数
};
people::~people()
{
  cout << "父类内析构函数调用" << endl;
}
//男人
class man :public people
{
public:
  man(string _name)//查看是否调用
  {
  cout << "子类内构造函数调用" << endl;
  this->_name = new string(_name);//对名字进行初始化
  }
  ~man()//查看是否调用
  {
  if (_name != NULL)
  {
    cout << "子类内析构函数调用" << endl;
    delete _name;
    _name = NULL;
  }
  }
  void come()
  {
  cout <<*_name<<"来咯" << endl;
  }
  string* _name;//用指针来管理名字
};
void test1()
{
  people p;
}
int main()
{
  test1();
  return 0;
}

6de278e6d6694ce5bb08e7e842b7e74b.png


面向对象结束,接下来是什么?


随着石碑倒下,看着眼前的楼梯,我心情沉重,“面向对象结束了,那接下来会是什么?”


本章知识点(图片形式)


7a399525ddec4b77923c464820b33738 (1).png


相关文章
|
9月前
|
Java 数据库连接 应用服务中间件
JavaWeb CRUD 与分页系统架构学习教程
本教程将带你一步步构建一个 Java Web 的 CRUD(创建、读取、更新、删除)及分页功能的示例应用,涵盖从基本概念到完整项目架构的各个层次。
220 3
|
网络协议 Ubuntu 前端开发
好好的容器突然起不来,经定位是容器内无法访问外网了?测试又说没改网络配置,该如何定位网络问题
本文记录了一次解决前端应用集成到主应用后出现502错误的问题。通过与测试人员的沟通,最终发现是DNS配置问题导致的。文章详细描述了问题的背景、沟通过程、解决方案,并总结了相关知识点和经验教训,帮助读者学习如何分析和定位网络问题。
640 1
|
弹性计算 分布式计算 DataWorks
MaxCompute操作报错合集之运行pyodps报错超时,该如何排查
MaxCompute是阿里云提供的大规模离线数据处理服务,用于大数据分析、挖掘和报表生成等场景。在使用MaxCompute进行数据处理时,可能会遇到各种操作报错。以下是一些常见的MaxCompute操作报错及其可能的原因与解决措施的合集。
269 6
|
人工智能 前端开发 JavaScript
前端资深技术专家苏千的“三迁”故事
他是如何从“苏千”变成“苏不迁”的。
前端资深技术专家苏千的“三迁”故事
|
物联网 5G 测试技术
Numerology | 带你读《5G 空口设计与实践进阶 》之十六
为了支持多种多样的部署场景,适应从低于 1 GHz 到毫米波的频谱范围,NR 引入了灵活可变的 OFDM Numerology。Numerology 是 OFDM 系统的基础参数集合,包含子载波间隔、循环前缀、TTI 长度和系统带宽等。
Numerology | 带你读《5G 空口设计与实践进阶 》之十六
|
关系型数据库 MySQL Windows
Windows 10下安装Mysql 5.7
mysql软件下载 mysql官方下载地址 01 02 03 04 mysql软件安装 05 06 07 08 09 10 ...
1107 0