第七层:多态(下)

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

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


#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


相关文章
|
1天前
|
存储 编译器 数据安全/隐私保护
【C++】多态
多态是面向对象编程中的重要特性,允许通过基类引用调用派生类的具体方法,实现代码的灵活性和扩展性。其核心机制包括虚函数、动态绑定及继承。通过声明虚函数并让派生类重写这些函数,可以在运行时决定具体调用哪个版本的方法。此外,多态还涉及虚函数表(vtable)的使用,其中存储了虚函数的指针,确保调用正确的实现。为了防止资源泄露,基类的析构函数应声明为虚函数。多态的底层实现涉及对象内部的虚函数表指针,指向特定于类的虚函数表,支持动态方法解析。
10 1
|
2月前
|
Java 编译器
多态
多态
16 2
|
6月前
|
C++
c++多态
c++多态
52 0
|
6月前
|
存储 C++
C++:多态
C++:多态
46 0
|
6月前
|
存储 编译器 C++
|
6月前
|
编译器 C++
【C++】:多态
【C++】:多态
60 0
|
编译器 C++
|
编译器
多态的初识
多态的初识