网站建设的广告语,泉州seo不到首页不扣费,建设网站服务请示,给公司做企业网站1.介绍一下你对面向对象的理解#xff0c;
面向对象编程#xff08;Object-Oriented Programming#xff0c;简称OOP#xff09;是一种编程范式#xff0c;它将数据和操作数据的方法组合成一个对象#xff0c;以此来描述现实世界中的事物和概念。在面向对象编程中#…1.介绍一下你对面向对象的理解
面向对象编程Object-Oriented Programming简称OOP是一种编程范式它将数据和操作数据的方法组合成一个对象以此来描述现实世界中的事物和概念。在面向对象编程中程序被组织成一个个对象每个对象都有自己的属性和方法对象之间通过消息传递来进行通信和协作。
与面向过程编程相比面向对象编程更加注重数据的封装和抽象使得程序更加易于维护和扩展。面向过程编程则更加注重流程和算法的设计程序的执行过程是由一系列的函数调用和数据传递组成的。
总的来说面向对象编程更加适合大型复杂的软件系统的开发而面向过程编程则更加适合简单的、流程性的程序设计。
面向对象的三大特性
面向对象编程Object-Oriented Programming简称OOP的三大特性是封装、继承和多态。
1. 封装Encapsulation封装是指将数据和对数据的操作封装在一个类中通过定义类的属性和方法来控制对数据的访问。封装可以隐藏内部实现细节只暴露必要的接口给外部使用提高了代码的可维护性和安全性。
2. 继承Inheritance继承是指一个类可以继承另一个类的属性和方法。通过继承子类可以重用父类的代码并且可以在不修改父类的情况下扩展或修改其功能。继承可以建立类之间的层次关系提高代码的可重用性和扩展性。
3. 多态Polymorphism多态是指同一个方法可以根据不同的对象调用出不同的行为。多态通过方法的重写和方法的重载实现。方法的重写Override是指子类可以重写父类的方法以实现自己的特定行为。方法的重载Overload是指在一个类中可以定义多个同名但参数列表不同的方法根据传入的参数类型和个数来决定调用哪个方法。多态提高了代码的灵活性和可扩展性使得程序可以根据实际情况做出不同的处理。
介绍一下c面向对象中的封装
在C中封装是面向对象编程的一个重要概念。它指的是将数据和操作数据的函数即方法封装在一个单独的实体中这个实体被称为类。封装的目的是将数据和方法组合在一起形成一个独立的、可复用的模块同时隐藏内部的实现细节只暴露必要的接口给外部使用。
封装通过访问控制符来实现对类的成员的访问限制。C中有三种访问控制符public、private和protected。
- public公有成员可以在类的内部和外部被访问。它们可以被类的对象直接访问也可以被类的成员函数访问。 - private私有成员只能在类的内部被访问。它们不能被类的对象直接访问只能通过类的公有成员函数来访问。 - protected受保护成员类似于私有成员但可以在派生类中被访问。
封装的优点有
1. 数据隐藏封装可以隐藏类的内部实现细节只暴露必要的接口给外部使用提高了代码的安全性和可维护性。 2. 代码复用封装将数据和方法组合在一起形成一个独立的模块可以在不同的地方重复使用提高了代码的复用性。 3. 简化接口封装可以将复杂的内部实现封装起来对外部提供简单的接口降低了使用者的使用难度。
介绍一下c面向对象中的继承
C面向对象中的继承是指一个类可以从另一个类中继承属性和方法。被继承的类称为基类或父类继承的类称为派生类或子类。继承可以使代码重用更加方便同时也可以使代码更加易于维护和扩展。
在C中继承有三种类型公有继承、私有继承和保护继承。公有继承是最常用的一种继承方式它使得派生类可以访问基类的公有成员和方法但不能访问基类的私有成员和方法。私有继承和保护继承则分别限制了派生类对基类成员的访问权限。
父类中所有非静态成员属性都会被子类继承下去
父类中私有属性 是被编译器隐藏了 因此访问不到 但是的确继承下去了
菱形继承一个类被俩个类继承 这俩个又被一个类继承
继承的类型有哪些
C的继承分为三种: 公有继承 保护继承 私有继承
C多态怎么理解
C多态是指在面向对象编程中同一个函数名可以有多种不同的实现方式这些实现方式可以根据不同的对象类型进行调用从而实现不同的行为。
C多态的实现方式主要有两种虚函数和模板函数。
虚函数是指在基类中声明一个函数为虚函数在派生类中重写该函数通过基类指针或引用调用该函数时会根据实际指向的对象类型来调用相应的函数实现。
模板函数是指在函数定义时使用模板参数可以根据不同的参数类型生成不同的函数实现从而实现多态。
C多态的优点是可以提高代码的可扩展性和可维护性使得代码更加灵活和易于扩展。
类和对象的区别和联系
类是一种抽象的概念它是对一类具有相同属性和行为的对象的描述。类定义了对象的属性和方法它是创建对象的模板。类可以看作是一个蓝图或者是一个定义它描述了对象应该具有的特征和行为。
对象是类的实例化它是类的具体实体。对象是根据类的定义创建的它具有类定义的属性和方法。每个对象都是独立的它们可以有自己的状态和行为。
类和对象之间有以下联系和区别
1. 关系类是对象的抽象对象是类的具体实例。类是对象的模板而对象是类的具体化。
2. 属性和方法类定义了对象的属性和方法而对象具有类定义的属性和方法。类中的属性和方法是共享的而对象的属性和方法是独立的。
3. 创建类是在编码阶段定义的而对象是在运行时创建的。
4. 多个对象一个类可以创建多个对象每个对象都是独立的它们可以有自己的状态和行为。
5. 继承类可以通过继承创建子类子类继承了父类的属性和方法并可以添加自己的属性和方法。
总结来说类是对一类对象的抽象描述而对象是类的具体实例。类定义了对象的属性和方法而对象具有类定义的属性和方法。类和对象之间是一种抽象和具体的关系。
重载,重写 隐藏的区别
重载作用域相同函数名相同
重写父类的方法子类重写要求父类的该方法必须是虚函数或者纯虚函数virtual
隐藏父类的方法子类重写要求父类的该方法不能被virtual修饰
explicit作用 关闭函数的类型自动转换防止隐式转换
空类占用内存空间1字节
静态成员变量
概念成员变量和成员函数前加一个static称为静态成员
目的为了实现一个类的不同对象之间的数据和函数共享。
• 所有对象共享同一份数据
• 在编译阶段分配内存
• 类内的声明类外初始化
静态成员函数
a.所有对象共享同一个函数
b.静态成员函数只能访问静态成员变量
在C中类内的成员变量和成员函数分开存储、只有非静态成员变量才属于类的对象上
this指针当形参和成员变量同名时可用this指针来区分(解决同名冲突)、在类的非静态成员函数中返回对象本身可使用return * this
2.内联函数
介绍一下内联函数
如果一个函数是内联的那么在编译时编译器会把该函数的代码副本放置在每个调用该函数的地方。
对内联函数进行任何修改都需要重新编译函数的所有客户端因为编译器需要重新更换一次所有的代码否则将会继续使用旧的函数。 如果想把一个函数定义为内联函数则需要在函数名前面放置关键字inline在调用函数之前需要对函数进行定义。如果已定义的函数多于一行编译器会忽略 inline 限定符。 内联函数的作用
引入内联函数的目的是为了解决程序中函数调用的效率问题程序在编译器编译的时候编译器将程序中出现的内联函数的调用表达式用内联函数的函数体进行替换而对于其他的函数都是在运行时候才被替代。
内联函数的使用场合
首先使用inline函数可以完全取代表达式形式的宏定义。 内联函数在C类中应用最广的应该是用来定义存取函数。我们定义的类中一般会把数据成员定义成私有的或者保护的这样外界就不能直接读写我们类成员的数据了。对于私有或者保护成员的读写就必须使用成员接口函数来进行。如果我们把这些读写成员函数定义成内联函数的话将会获得比较好的效率。在类定义中的定义的函数都是内联函数即使没有使用inline 说明符。
class A
{private:int nTest;
public:int readTest()
{return nTest;}void setTest(int i);
};inline void A::setTest(int i)
{nTest i;
};
类A的成员函数readTest()和setTest()都是inline函数。readTest()函数的定义体被放在类声明之中因而readTest()自动转换成inline函数setTest()函数的定义体在类声明之外因此要加上inline关键字。
内联函数与宏有什么区别 1内联函数在编译时展开宏在预编译时展开。 2在编译的时候内联函数可以直接被镶嵌到目标代码中而宏只是一个简单的文本替换。 3内联函数可以完成诸如类型检测、语句是否正确等编译功能宏就不能具有这样的功能。 4宏不是函数inline函数是函数。 5宏在定义时要小心处理宏参数一般情况是把参数用括号括起来否则容易出现二义性。而内联函数定义时不会出现二义性。
为什么不把所有的函数都定义成内联函数
内联是以代码膨胀复制为代价的仅仅省去了函数调用的开销从而提高函数的执行效率。如果执行函数体内代码的时间相比于函数调用的开销较大那么效率的收获会很少。另一方面每一处内联函数的调用都要复制代码将使程序的总代码量增大消耗更多的内存空间。
以下情况不宜使用内联 1如果函数体内的代码比较长使用内联将导致内存消耗代价较高。 2如果函数体内出现循环那么执行函数体内代码的时间要比函数调用的开销大。
3.delete []和delete的区别
delete和delete[]都是用于释放动态分配的内存空间的操作符但它们的使用场景和效果是不同的。
delete用于释放单个对象的内存空间它会调用该对象的析构函数然后释放该对象所占用的内存空间。
delete[]用于释放数组对象的内存空间它会调用数组中每个元素的析构函数然后释放整个数组所占用的内存空间。
如果使用delete释放数组对象的内存空间会导致未定义行为因为它只会释放数组中第一个元素所占用的内存空间而不会释放整个数组所占用的内存空间。反之如果使用delete[]释放单个对象的内存空间也会导致未定义行为因为它会调用一个不存在的析构函数。因此使用delete和delete[]时要根据动态分配内存的方式来选择合适的操作符。
4.虚函数是用来干嘛的虚函数机制怎么实现的虚表指针在内存中的存放位置
虚函数是用来实现多态性的一种机制。它允许在基类中声明一个虚函数在派生类中进行重写从而实现基类指针或引用调用派生类对象的函数时能够根据实际对象的类型来调用相应的函数。
虚函数机制的实现通常是通过虚表vtable来实现的。每个包含虚函数的类都会有一个对应的虚表虚表中存放着指向各个虚函数的函数指针。当对象被创建时会在对象的内存布局中添加一个指向虚表的指针通常称为虚表指针vptr。
虚表指针通常存放在对象的内存布局的最前面即对象的起始位置。通过虚表指针程序可以在运行时动态地确定对象的实际类型并根据实际类型调用相应的虚函数。
5.C为什么有指针还要引用
C中指针和引用都是用来处理内存地址的但它们有不同的用途和特点。
指针是一个变量它存储了一个内存地址可以通过解引用操作符(*)来访问该地址上的值。指针可以被重新赋值也可以被赋值为NULL因此它具有更大的灵活性和可变性。指针还可以进行算术运算比如指针加减操作这在某些场景下非常有用。
引用是一个别名它是已经存在的变量的别名不占用额外的内存空间。引用不能被重新赋值一旦被初始化就一直指向同一个变量。引用通常用于函数参数传递和返回值可以避免拷贝大量的数据提高程序的效率。
因此指针和引用各有其优点和适用场景需要根据具体情况选择使用哪种方式。
6.vector实现的机制是怎么样的
Vector是C STL中的一个容器它是一个动态数组可以根据需要自动扩展或缩小。Vector的实现机制是通过一个连续的内存块来存储元素当元素数量超过当前内存块的大小时会自动申请更大的内存块并将原有元素复制到新的内存块中然后释放原有内存块。
Vector的内部实现主要包括以下几个方面
1. 内存分配Vector使用动态内存分配当元素数量超过当前内存块的大小时会自动申请更大的内存块并将原有元素复制到新的内存块中然后释放原有内存块。
2. 元素访问Vector的元素可以通过下标访问也可以通过迭代器访问。Vector的下标访问是通过指针偏移实现的而迭代器访问是通过指针实现的。
3. 插入和删除Vector的插入和删除操作会导致元素的移动因此效率较低。在插入和删除元素时Vector会将后面的元素向后移动或向前移动以保证元素的连续性。
4. 内存管理Vector的内存管理是由STL库自动完成的用户不需要手动管理内存。Vector会自动分配和释放内存以保证内存的正确使用。
7.迭代器有了解吗讲解一下你的理解
C迭代器是一种用于遍历容器中元素的对象它提供了一种通用的方式来访问容器中的元素而不需要了解容器的内部实现细节。迭代器可以被看作是一种指针它指向容器中的某个元素并提供了一些操作来访问和操作该元素。
迭代器可以分为五种类型输入迭代器、输出迭代器、前向迭代器、双向迭代器和随机访问迭代器。这些迭代器类型的区别在于它们支持的操作不同。输入迭代器和输出迭代器只支持单向遍历前向迭代器支持单向遍历和单个元素的插入和删除双向迭代器支持双向遍历和单个元素的插入和删除而随机访问迭代器则支持随机访问和所有元素的插入和删除。
使用迭代器可以方便地遍历容器中的元素而不需要了解容器的内部实现细节。迭代器还可以用于算法中例如排序、查找、拷贝等操作。在使用迭代器时需要注意迭代器的有效性避免使用无效的迭代器访问容器中的元素。
8.介绍一下C中深拷贝和浅拷贝的区别
浅拷贝是指将一个对象的值复制到另一个对象这两个对象将共享相同的内存地址。当其中一个对象修改了共享的数据时另一个对象也会受到影响。这种拷贝方式适用于简单的数据类型如整数、浮点数等。
深拷贝是指创建一个新的对象并将原始对象的所有成员变量的值复制到新对象中。这意味着新对象拥有独立的内存空间对新对象的修改不会影响原始对象。这种拷贝方式适用于包含动态分配内存的对象如指针、数组、字符串等。
9.如果系统中只有10K内存而我要分配12K能分配成功吗如果能那么将分配到的区域用memset进行初始化会成功吗
如果系统中只有10K内存而你要分配12K那么无法成功分配。因为内存分配需要满足连续的内存空间而系统中只有10K的内存空间是不足以满足12K的需求的。
即使你能够分配到12K的内存空间使用memset进行初始化也可能会失败。因为memset函数需要访问和修改内存空间如果你超出了系统分配给你的内存空间就会导致访问越界可能会引发程序崩溃或其他不可预测的行为。 10.C11有哪些新特性
1. 自动类型推导使用 auto 关键字可以让编译器自动推导变量的类型。
2. Lambda 表达式Lambda 表达式是一种匿名函数可以在代码中直接定义和使用。
3. 右值引用和移动语义引入了右值引用和移动语义可以实现高效的对象移动和转移。
4. 智能指针引入了 unique_ptr、shared_ptr 和 weak_ptr 等智能指针可以自动管理动态分配的内存。
5. 范围 for 循环引入了范围 for 循环可以方便地遍历容器和数组。
6. 初始化列表引入了初始化列表可以方便地初始化对象和容器。
7. constexpr 函数和变量引入了 constexpr 关键字可以在编译时计算常量表达式。
8. 线程支持库引入了线程支持库可以方便地创建和管理线程。
9. 新的容器和算法引入了 unordered_map、unordered_set、array、tuple 等新的容器和算法。
11.c中auto是怎么实现的
在 C11 中auto 关键字被引入用于自动类型推导。auto 关键字可以让编译器自动推导变量的类型从而简化代码的书写。
auto 的实现原理是通过编译器在编译时进行类型推导根据变量的初始化表达式来推导变量的类型。编译器会根据初始化表达式的类型来推导变量的类型并将其替换为实际的类型。
智能指针了解吗
智能指针是一种 C 中的类模板它可以自动管理动态分配的内存避免内存泄漏和悬挂指针等问题。智能指针的主要作用是在对象生命周期结束时自动释放内存从而避免手动释放内存的繁琐和容易出错的过程。
智能指针有多种类型包括 unique_ptr、shared_ptr、weak_ptr 等。其中unique_ptr 是独占式智能指针它只能有一个指针指向同一块内存当 unique_ptr 被销毁时它所指向的内存也会被自动释放。shared_ptr 是共享式智能指针它可以有多个指针指向同一块内存当最后一个 shared_ptr 被销毁时它所指向的内存才会被自动释放。weak_ptr 是一种弱引用智能指针它可以指向 shared_ptr 所管理的内存但不会增加内存的引用计数因此不会影响内存的释放。 12.什么是右值右值引用
在 C 中表达式可以分为左值和右值两种类型。左值是指可以取地址的表达式即表达式的结果可以被赋值给一个变量或者指针。右值是指不能取地址的表达式即表达式的结果不能被赋值给一个变量或者指针。
右值引用是 C11 引入的一种新的引用类型右值引用使用 符号表示可以绑定到临时对象右值或将要销毁的对象用于实现移动语义和完美转发。
右值引用的主要作用有两个 1. 移动语义右值引用可以绑定到临时对象这些临时对象在表达式结束后将被销毁。通过使用移动构造函数和移动赋值运算符可以将临时对象的资源如堆内存转移到新的对象上避免了不必要的内存拷贝提高了性能。 2. 完美转发右值引用还可以用于实现完美转发即在函数调用中将参数以原始的形式传递给其他函数避免了多次拷贝和类型转换。通过使用模板和右值引用可以实现通用的转发函数将参数按照原始类型和值类别转发给其他函数。 13.shared_ptr使用中可能存在的问题
1. 循环引用当多个 shared_ptr 相互引用时可能会导致循环引用的问题。这会导致内存泄漏因为这些对象的引用计数永远不会降为零无法释放内存。为了解决这个问题可以使用 weak_ptr 来打破循环引用。
2. 线程安全性shared_ptr 的引用计数是线程安全的但是对象本身的访问并不是线程安全的。如果多个线程同时访问同一个 shared_ptr 所管理的对象可能会导致竞争条件和数据不一致的问题。为了解决这个问题可以使用互斥锁或原子操作来保护共享资源。
3. 不适用于部分场景shared_ptr 适用于多个指针共享同一块内存的场景但并不适用于所有情况。例如当需要在多个线程中传递指针所有权时shared_ptr 并不是最佳选择因为它的引用计数需要进行原子操作可能会影响性能。
4. 对象销毁时机不确定由于 shared_ptr 是通过引用计数来管理内存的当最后一个 shared_ptr 被销毁时对象的析构函数会被调用但具体的销毁时机是不确定的。这可能会导致一些资源的延迟释放问题例如文件句柄、数据库连接等。
5. 对象的大小shared_ptr 内部需要维护引用计数和指向对象的指针因此会增加对象的大小。如果需要管理大量的小对象使用 shared_ptr 可能会导致内存开销较大。
14.weak_ptr是用来干嘛的怎么保证用weak_ptr不会崩溃
weak_ptr是用来解决shared_ptr的循环引用问题的。当两个或多个对象相互引用时如果使用shared_ptr会导致它们之间形成循环引用导致内存泄漏。而使用weak_ptr可以避免这种情况。
weak_ptr是一种弱引用它不会增加引用计数也不会阻止对象被销毁。当需要使用对象时可以通过lock()方法获取一个shared_ptr如果对象已经被销毁则返回一个空的shared_ptr。
为了保证使用weak_ptr不会崩溃需要注意以下几点
1. 在使用weak_ptr之前需要先判断它是否已经过期即是否为空。
2. 在使用lock()方法获取shared_ptr时需要先判断返回的shared_ptr是否为空以避免访问已经被销毁的对象。
3. 在使用weak_ptr时需要保证其对应的shared_ptr对象还存在否则会导致程序崩溃。
4. 在使用weak_ptr时需要注意避免循环引用的问题否则会导致内存泄漏。
15.constexpr 函数和变量的作用与const的区别
constexpr是C11引入的关键字用于声明函数或变量为编译时常量。它的作用是告诉编译器在编译时就可以计算出函数或变量的值而不需要在运行时进行计算。
对于constexpr函数它必须满足以下条件 1. 函数体内只能包含一条return语句。 2. 函数的参数和返回值类型必须是字面值类型literal type。 3. 函数体内只能包含能在编译时计算的语句如赋值、条件语句等。
constexpr变量则是指在编译时就可以确定其值的常量。它的声明方式与普通变量相同只需在声明前加上constexpr关键字。
与const的区别在于const关键字用于声明运行时常量而constexpr关键字用于声明编译时常量。const变量的值可以在运行时确定而constexpr变量的值必须在编译时确定。constexpr函数和变量在编译时会被计算出结果并在编译过程中被替换为其计算结果从而提高程序的性能。
总结起来constexpr用于声明编译时常量而const用于声明运行时常量。constexpr函数和变量在编译时计算而const变量在运行时计算。 15.介绍一下Lambda 表达式他有什么用
Lambda表达式是一种匿名函数它可以作为参数传递给其他函数或方法。Lambda表达式可以简化代码使代码更加简洁和易于阅读。
lamada表达式中mutable 关键字有什么用
mutable关键字用于指定lambda表达式是否可以修改其捕获的变量。
当我们在lambda表达式中捕获一个变量时默认情况下该变量是只读的即不能在lambda表达式内部修改它的值。这是因为lambda表达式默认是const的。
然而有时我们可能需要在lambda表达式内部修改捕获的变量的值。这时就可以使用mutable关键字。通过在lambda表达式的参数列表后面加上mutable关键字我们可以将捕获的变量声明为可修改的在lambda表达式外部变量的值仍然保持不变。mutable关键字只对捕获的变量有效对于lambda表达式内部的局部变量是无效的mutable 关键字可以在不修改对象的情况下在表达式中创建新的可变对象。
16.当初始化列表时被初始化的顺序是声明的顺序不是列表顺序。
17.new与malloc的区别 特性:new/delete是C关键字需要编译器支持。malloc/free是库函数需要头文件支持。 参数:使用new操作符申请内存分配时无须指定内存块的大小编译器会根据类型信息自行计算。而malloc则需要显式地指出所需内存的尺寸。
返回类型:new操作符内存分配成功时返回的是对象类型的指针类型严格与对象匹配无须进行类型转换故new是符合类型安全性的操作符。而malloc内存分配成功则是返回void * 需要通过强制类型转换将void*指针转换成我们需要的类型。
分配失败: new内存分配失败时会抛出bac_alloc异常。malloc分配内存失败时返回NULL。
特性:new/delete是C关键字需要编译器支持。malloc/free是库函数需要头文件支持。
参数:使用new操作符申请内存分配时无须指定内存块的大小编译器会根据类型信息自行计算。而malloc则需要显式地指出所需内存的尺寸。 18.C与C的区别 C是面向过程的语言而C是面向对象的语言
• C只能写面向过程的代码而C既可以写面向过程的代码也可以实现面向对象的代码
• C和强制类型转换上也不一样 const_cast static_cast reinterpret_cast dynamic_cast
• C和C的输入输出方式也不一样
• C引⼊入 new/delete 运算符取代了了C中的 malloc/free 库函数
• C引⼊入引⽤用的概念
• C引⼊入类的概念
• C引⼊入函数重载的特性
19.前置与后置区别
后置中tmp是一个临时对象会造成一次构造函数和一次析构函数的额外开销 效率高前置不产生临时对象
20.友元 friend
友元让一个函数或者类访问另一个类的私有成员(打破封装)
三种实现
• 全局函数做友元
• 类做友元(友元类)
• 成员函数做友元
21.虚函数与纯虚函数的区别
虚函数和纯虚函数是面向对象编程中的概念用于实现多态性。
虚函数是在基类中声明的函数可以被派生类重写。(通过运行阶段才能知道需要调用那个对象)当通过基类指针或引用调用虚函数时实际调用的是派生类中的重写函数。虚函数通过在基类中使用关键字virtual来声明派生类中可以选择是否重写虚函数。
纯虚函数是在基类中声明的没有实际实现的函数它只是作为接口存在要求派生类必须实现该函数。纯虚函数通过在基类中使用关键字virtual和 0来声明派生类必须实现纯虚函数否则派生类也会成为抽象类。
区别如下 1. 虚函数可以有实现而纯虚函数没有实现。 2. 虚函数可以被派生类选择性地重写而纯虚函数必须在派生类中实现。 3. 含有纯虚函数的类称为抽象类不能实例化对象只能作为基类使用。而含有虚函数的类可以实例化对象。 4. 如果一个类中包含了纯虚函数那么它就是一个抽象类派生类必须实现纯虚函数才能被实例化。 5. 虚函数可以有默认实现而纯虚函数没有默认实现。
总结来说虚函数是可以有实现的而纯虚函数没有实现必须在派生类中实现。虚函数可以选择性地重写而纯虚函数必须在派生类中实现。
22.虚析构和纯虚析构
虚析构作用使用父类指针释放子类对象时可以让子类的析构函数和父类的析构函数同时被调用到。
虚析构和纯虚析构共性
• 可以解决父类指针释放子类对象
• 都需要具体的函数实现
实现
虚析构语法virtual ~类名{}
纯虚析构语法virtual ~类名 0
纯虚析构实现类名~类名{}