做网站和网页区别,四川省建设厅门户网站,wordpress 爆破,网站做支付点击蓝字关注我们21、构造函数和析构函数可以调用虚函数吗#xff0c;为什么在C中#xff0c;提倡不在构造函数和析构函数中调用虚函数#xff1b;在构造函数和析构函数调用的所有函数(包括虚函数)都是编译时确定的, 虚函数将运行该类中的版本.因为父类对象会在子类之前进行… 点击蓝字关注我们21、构造函数和析构函数可以调用虚函数吗为什么在C中提倡不在构造函数和析构函数中调用虚函数在构造函数和析构函数调用的所有函数(包括虚函数)都是编译时确定的, 虚函数将运行该类中的版本.因为父类对象会在子类之前进行构造此时子类部分的数据成员还未初始化因此调用子类的虚函数时不安全的故而C不会进行动态联编析构函数是用来销毁一个对象的在销毁一个对象时先调用子类的析构函数然后再调用基类的析构函数。所以在调用基类的析构函数时派生类对象的数据成员已经销毁这个时候再调用子类的虚函数没有任何意义。22、构造函数的执行顺序析构函数的执行顺序构造函数内部干了啥拷贝构造干了啥构造函数顺序:基类构造函数。如果有多个基类则构造函数的调用顺序是某类在类派生表中出现的顺序而不是它们在成员初始化表中的顺序。成员类对象构造函数。如果有多个成员类对象则构造函数的调用顺序是对象在类中被声明的顺序而不是它们出现在成员初始化表中的顺序。派生类构造函数。析构函数顺序:调用派生类的析构函数调用成员类对象的析构函数调用基类的析构函数。23、虚析构函数的作用父类的析构函数是否要设置为虚函数C中基类采用virtual 虚析构函数是为了防止内存泄漏。如果派生类中申请了内存空间并在其析构函数中对这些内存空间进行释放。假设基类中采用的是非虚析构函数当删除基类指针指向的派生类对象时就不会触发动态绑定因而只会调用基类的析构函数而不会调用派生类的析构函数。那么在这种情况下派生类中申请的空间就得不到释放从而产生内存泄漏。所以为了防止这种情况的发生C中基类的析构函数应采用virtual 虚析构函数。纯虚析构函数一定得有定义因为每一个派生类析构函数会被编译器加以扩张以静态调用的方式调用其每一个虚基类以及上一层基类的析构函数。因此缺乏任何一个基类析构函数的定义就会导致链接失败。因此最好不要把虚析构函数定义为纯虚析构函数。24、构造函数析构函数可以调用虚函数吗在构造函数和析构函数中最好不要调用虚函数在构造函数和析构函数中调用的成员函数都是属于编译时确定的,并不具有虚函数的动态绑定特性, 有如下原因:在构造时, 父类对象总是先于子类对象构造的, 如果父类的析构函数使用虚函数机制调用子类的函数, 结果将是不可预料的在析构时, 子类的析构函数总是先于父类执行, 如果父类的析构函数使用虚函数机制调用子类的函数, 结果将是不可预料的参考: 21、构造函数和析构函数可以调用虚函数吗为什么25、构造函数, 析构函数可否抛出异常构造函数异常使用智慧指针来管理堆内存. 其不需要在析构函数中手动释放资源. 在发生异常时, 智慧指针会自动释放资源从而避免了内存泄漏.一般建议不要在构造函数里做过多的资源分配。(原因):C拒绝为没有完成构造函数的对象调用析构函数原因是避免开销构造函数中发生异常控制权转出构造函数。如果构造函数中申请了堆内存, 则堆内存将无法释放, 从而造成内存泄漏例如: 在对象b 的构造函数中发生异常对象b 的析构函数不会被调用。因此会造成内存泄漏。后果:解决方案:析构函数异常(后果1): 如果某一个异常发生,某对象的析构函数被调用,而此时析构发生了异常并流出了函数之外,则函数会被立即terminate掉(函数外有catch也不能拯救)如果异常不可避免则应在析构函数内捕获而不应当抛出。在析构函数中使用try-catch块屏蔽所有异常。在异常传递的堆栈辗转开解的过程中, 如果发生析构异常, C会调用terminate终止程序如果析构函数发生发生异常则异常后面的代码将不执行无法确保完成我们想做的清理工作。后果:解决方法附加说明:26、类如何实现只能静态分配和只能动态分配建立类的对象有两种方式动态建立类对象, 使用new操作符将在堆空间分配内存, 然后调用构造函数初始化这片内存空间.这种方法间接调用类的构造函数。静态建立一个类对象就是由编译器为对象在栈空间中分配内存, 然后调用构造函数初始化这片内存空间.使用这种方法直接调用类的构造函数。静态建立(栈空间)动态建立(堆空间)A *p new A();只能在堆上建立静态建立:编译器在为类对象分配栈空间时会先检查类的析构函数的访问性由此引发的问题:代码如下class A { protected : A(){} ~A(){} public : static A* create() { return new A(); } void destory() { delete this ; } };当对象建立在栈上面时是由编译器分配内存空间的调用构造函数来构造栈对象。当对象使用完后编译器会调用析构函数来释放栈对象所占的空间。编译器管理了对象的整个生命周期。其实不光是析构函数只要是非静态的函数编译器都会进行检查。如果类的析构函数是私有的则编译器不会在栈空间上为类对象分配内存。因此将析构函数设为私有类对象就无法建立在栈上了。因为析构函数设置为了私有需要设置一个public函数来调用析构函数分析: 类对象只能建立在堆上就是不能静态建立类对象即不能直接调用类的构造函数。实现方式: 将析构函数设为私有或则受保护方法分析:只能在栈上建立只有使用new运算符对象才会建立在堆上因此只要禁用new运算符就可以实现类对象只能建立在栈上。将operator new()设为私有即可。注意: 重载了new就需要重载delete代码如下class A { private : void * operator new ( size_t t){} // 注意函数的第一个参数和返回值都是固定的 void operator delete ( void * ptr){} // 重载了new就需要重载delete public : A(){} ~A(){} };参考:在堆/栈上建立对象如何定义一个只能在堆上栈上生成对象的类?27、如果想将某个类用作基类为什么该类必须定义而非声明因为在继承体系下, 子类会继承父类的成员, 并且编译器会在子类的构造函数和析构函数中插入父类的构造和析构部分, 因而父类必须有定义.28、什么情况会自动生成默认构造函数四种情况:类成员对象带有默认构造函数.基类带有默认构造函数类中存在虚函数继承体系中存在虚继承在合成的默认构造函数中只有基类子对象和类类型对象会被初始化而其他所有的非静态成员(如整数指针数组等)都不会初始化对他们进行初始化的应该是程序员而非编译器。注意值类型的默认值并不是默认构造的初始化。29、什么是类的继承类与类之间的关系(has-A)包含关系即一个类的成员属性是另一个已经定义好的类(use-A)使用关系, 一个类使用另一个类通过类之间的成员函数相互联系定义友元或者通过传递参数的方式实现(is-A)继承关系, 继承关系关系具有传递性继承的相关概念所谓的继承就是一个类继承了另一个类的属性和方法这个新的类包含了上一个类的属性和方法被称为子类或者派生类被继承的类称为父类或者基类继承的特点子类拥有父类的所有属性和方法子类对象可以当做父类对象使用子类可以拥有父类没有的属性和方法继承中的访问控制public、protected、private继承中的构造和析构函数子类中构造函数的调用顺序为: 基类构造函数, 成员对象构造函数, 派生类构造函数子类中析构函数的调用顺序为: 派生类析构函数, 成员对象析构函数, 基类析构函数继承中的兼容性原则类型兼容规则是指在需要基类对象的任何地方都可以使用公有派生类的对象来替代。参考: 继承中的类型兼容性原则 - Say舞步 - 博客园30、什么是组合一个类里面的数据成员是另一个类的对象即内嵌其他类的对象作为自己的成员如果内嵌类没有零参数构造函数 则必须使用初始化列表进行初始化构造函数的执行顺序按照内嵌对象成员在组合类中的定义顺序调用内嵌对象的构造函数。然后执行组合类构造函数的函数体析构函数调用顺序相反。*声明本文于网络整理版权归原作者所有如来源信息有误或侵犯权益请联系我们删除或授权事宜。戳“阅读原文”我们一起进步