析构函数

C++之保护和私有构造函数与析构函数

落花浮王杯 提交于 2020-04-06 19:07:58
原文: http://blog.chinaunix.net/uid-22312037-id-3811654.html 参考: http://blog.sina.com.cn/s/blog_4c4d6e740100upwp.html 一、构造函数 1、保护 构造函数定义为protected后,就意味着你不能在类的外部构造对象了,而只能在外部构造该类的子类的对象,比如: class Base { protected: Base() {} ... }; class Derived : public Base { public: Derived() {} ... }; Base b; //error Derived d; //ok 2、私有 构造函数定义为private后,意味着不仅仅不能在类的外部构造对象了,而且也不能在外部构造该类的子类的对象了,只能通过类的static静态函数来访问类的内部定义的对象,单件singleton模式就是私有构造函数的典型实例: class CLog { private: CLog() {}; public: ~CLog() {}; public: static CLog* GetInstance() { if (NULL == m_sopLogInstance) { CLock oInstanceLock; oInstanceLock.Lock(); if

何时使用虚拟析构函数?

隐身守侯 提交于 2020-04-06 13:07:41
问题: I have a solid understanding of most OO theory but the one thing that confuses me a lot is virtual destructors. 我对大多数面向对象理论有扎实的了解,但令我困惑的一件事是虚拟析构函数。 I thought that the destructor always gets called no matter what and for every object in the chain. 我以为无论链中的每个对象是什么,析构函数总是被调用。 When are you meant to make them virtual and why? 您打算何时将它们虚拟化?为什么? 解决方案: 参考一: https://stackoom.com/question/1vyl/何时使用虚拟析构函数 参考二: https://oldbug.net/q/1vyl/When-to-use-virtual-destructors 来源: oschina 链接: https://my.oschina.net/stackoom/blog/3219050

析构函数不应该抛出异常

穿精又带淫゛_ 提交于 2020-04-06 03:59:32
1、构造函数可以抛出异常,但最好不要。 2、c++标准指明析构函数不能、也不应该抛出异常。 more effective c++关于第2点提出两点理由: 1)如果析构函数抛出异常,则异常点之后的程序不会执行,如果析构函数在异常点之后执行了某些必要的动作比如释放某些资源,则这些动作不会执行,会造成诸如资源泄漏的问题。 2)通常异常发生时,c++的机制会调用已经构造对象的析构函数来释放资源,此时若析构函数本身也抛出异常,则前一个异常尚未处理,又有新的异常,会造成程序崩溃的问题。 解决办法: 1)永远不要在析构函数抛出异常。 2)通常第一点有时候不能保证。可以采取如下的方法: ~ClassName() { try{ do_something(); } catch(){ //这里可以什么都不做,只是保证catch块的程序抛出的异常不会被扔出析构函数之外,即让程序吞下异常。或者调用std::abort()终止程序。 } } 来源: https://www.cnblogs.com/sophia-yun/archive/2013/05/09/3053589.html

构造函数、析构函数抛出异常的问题

亡梦爱人 提交于 2020-04-06 03:01:46
1.构造函数异常   C++中构造函数是一个与类同名,没有返回值的特殊函数,主要是构造对象,为对象分配资源,由于没有返回值,如何判断构造对象的过程一定成功呢?   答:参考链接 C++构造函数中抛出的异常 C++中通知对象构造失败的唯一方法只能是在构造函数中抛出异常,采用 throw语句 来实现 构造函数中抛出异常将导致对象的析构函数不被执行( 因构造未完成,当然不会构造,对于通过设置变量来表示构造失败,并不能阻止构造函数的执行,所以最后仍然会调用析构函数 ) 当对象发生部分构造,已经构造完成的子对象将逆序地被析构。 2. 析构函数异常 ( 参考 构造函数、析构函数抛出异常的问题 )   C++标准规定 析构函数不能、也不应该抛出异常 ,从某种意义上讲,析构函数是C++异常处理机制的一部分,但析构并不是说不会发生异常   2.1 more effective c++提出两点理由(析构函数不能抛出异常的理由):   1)如果析构函数抛出异常,则 异常点之后的程序不会执行 ,如果析构函数在异常点之后执行了某些必要的动作比如释放某些资源,则这些动作不会执行,会造成资源泄漏等问题。   2)通常异常发生时,c++的机制会调用已经构造对象的析构函数来释放资源,此时若析构函数本身也抛出异常,则前一个异常尚未处理,又有新的异常,会造成程序崩溃。   2.2 那么当无法保证在析构函数中不发生异常时

从C++到C++/CLI

落花浮王杯 提交于 2020-04-06 02:40:22
  刘未鹏(pongba) /文      看起来只是在C++后面多写了一个“/CLI”,然而其意义却远不止于此,google的c++.moderated版上为此还发起了数星期的讨论,在国内大部分人对C++/CLI还不是很了解的情况下,google上面已然硝烟四起...   就像我们作出其它任何选择一样,在选择之前最重要的是先要清楚为什么作出这样或那样的选择——C++/CLI到底提供了哪些优势?为什么我们(标准C++程序员)要选择C++/CLI而不是C#?我们能够得到什么?CLI平台会不会束缚C++的能力?   这些都是来自标准C++社区的疑问。从google上面的讨论看来,更多来自标准C++社区的程序员担心的是C++/CLI会不会约束标准C++的能力,或者改变标准C++发展的方向,也有一部分人对C++/CLI的能力持怀疑态度。另外一些人则是询问C++/CLI能够带来什么。   这些被提出的问题在google上面一一得到了答案。好消息是:情况比乐观的人所想象的或许还要更好一些——   世界改变了吗?   对于谙于标准C++的程序员来说,最为关心的还是:在C++/CLI中,世界还是他们熟悉的那个世界吗?在标准C++的世界里,他们手里的各种魔棒——操作符重载|模板|多继承(语言),STL|Boost|ACE(库)——还能挥舞出五彩缤纷的火焰吗?是不是标准C++到了

C++异常以及异常与析构函数

好久不见. 提交于 2020-04-06 01:31:35
1. 抛出异常 1.1 抛出异常(也称为抛弃异常)即检测是否产生异常,在C++中,其采用throw语句来实现,如果检测到产生异常,则抛出异常。 该语句的格式为: throw 表达式; 如果在try语句块的程序段中(包括在其中调用的函数)发现了异常,且抛弃了该异常,则这个异常就可以被try语句块后的某个catch语句所捕获并处理,捕获和处理的条件是被抛弃的异常的类型与catch语句的异常类型相匹配。由于C++使用数据类型来区分不同的异常,因此在判断异常时,throw语句中的表达式的值就没有实际意义,而表达式的类型就特别重要。 1.2 抛出异常实际是作为另一种返回值来使用的。 抛出异常的好处一是可 以不干扰正常的返回值 ,另一个是 调用者必须处理异常 ,而不像以前c语言返回一个整数型的错误码,调用者往往将它忽略了。 1.3 举例说明 假如说A方法掉调用-->B方法调用-->C方法。 然后在B和C方法里定义了throws Exception。A方法里定义了Try Catch。 那么调用A方法时,在执行到C方法里出现了异常,那么这个异常就会从C抛到B,再从B抛到A。在A里的try catch就会捕获这个异常,然后你就可以在catch写自己的处理代码。 那么为什么当时出现了异常不去处理呢? 因为你业务逻辑调用的是A方法,你执行了A方法,当然要在A里得到异常,然后来处理。如果在C里面就处理异常

C++语法之构造、析构函数

老子叫甜甜 提交于 2020-03-30 16:08:34
C++语法之构造、析构函数 众所周知,在类的一个对象被创建时,编译系统就会自动为该对象分配空间。但在分配空间后还会自动调用一个函数,这个函数我们就称为构造函数。构造函数的作用是为对象的成员变量赋初值。 构造函数:构造函数可以有各种参数形式,一个类可以有多个一般构造函数,前提是参数的个数或者类型不同(基于c++的重载函数原理)。创建对象时,根据对象的类型不停,调用不同的构造函数。当没有定义构造函数时系统就会生成隐式的构造函数,无任何实际作用。 例如: include using namespace std; class rec { public: rec(){cout<<"构造一个长方形甲\n";} rec(int l,int w){ length = l; width = w;cout << "长方形乙的面积为:" << length * width << endl;} rec(int l,int w,int h){ length=l ; width=w ; height=h ; cout<<"长方体丙的体积为:" <<length width height<<endl;} private: int length; int width; int height; }; void main() {//下面分别调用不同的构造函数 rec a; rec b(3,4); rec c(3,4

8.异常处理(未完)

[亡魂溺海] 提交于 2020-03-29 17:11:56
8.1.1栈展开 抛出异常时,将暂停当前函数的执行,开始查找匹配的catch子句。首先检查throw本身是否在try块内部,如果是,检查与该try相关的catch子句,看是否可以处理该异常。如果不能处理,就退出当前函数,并且释放当前函数的内存并销毁局部对象,继续到上层的调用函数中查找,直到找到一个可以处理该异常的catch。这个过程称为栈展开(stack unwinding)。当处理该异常的catch结束之后,紧接着该catch之后的点继续执行。当找不到匹配的catch时,程序将调用标准库函数terminate,负责终止程序的执行过程。 8.1.2析构函数能抛出异常吗? 不能, (1) 如果析构函数抛出异常,则异常点之后的程序不会执行,如果析构函数在异常点之后执行了某些必要的动作比如释放某些资源,则这些动作不会执行,会造成诸如资源泄漏的问题。 (2) 通常异常发生时,c++的机制会调用已经构造对象的析构函数来释放资源,此时若析构函数本身也抛出异常,则前一个异常尚未处理,又有新的异常,会造成程序崩溃的问题。 8.1.3异常对象和查找匹配的处理代码 异常对象使用异常抛出表达式来对异常对象进行拷贝初始化,因此throw语句中的表达式必须拥有完全类型,如果是类类型还必须拥有一个可访问的析构函数和拷贝或者移动构造函数。 异常的类型混合catch声明的类型匹配: (1

构造函数和析构函数基础

不打扰是莪最后的温柔 提交于 2020-03-26 00:02:43
//对象的初始化和清理用构造函数和析构函数 //编译器可以自己提供构造函数和析构函数 //构造函数和析构函数可以自己写 //构造函数用作成员属性初始化 //构造函数语法 类名(){} //构造函数没有返回值,函数名和类名相同,可以有参数,也可以没有。 //程序在调用对象时自动调用构造函数,不需要手动调用,且只调用一次 //析构函数 ~类名(){} //析构函数不可以有参数 #include<iostream> using namespace std; class person { public: //构造函数 person() { cout << "构造函数调用" << endl; } //析构函数 ~person() { cout << "~析构代码" << endl; //对象执行完后,才调用 } }; int main() { person A1; //创建对象时自动调用一次构造函数 person A2; system("pause"); return 0; } 来源: https://www.cnblogs.com/gjbhpu0308/p/12570639.html

c++学习笔记一

我们两清 提交于 2020-03-22 14:54:28
定一个头文件person.h包含类的声明:每行后面的注释是学习过程中的体会与思考 #include<iostream> #ifndef PERSON_H_ #define PERSON_H_ class Person { private: int ID;//只有静态的常量数据成员才可以在类中初始化,与C#不一样 std::string Name; int Age; double Money; char * Address;//定义一个字符串指针成员 static int PersonNum;//定义一个静态变量记录对象的个数,静态变量要在源文件中初始化,如果没初始化会有错误,为什么? public: Person();//默认的构造函数 Person(int id,std::string name,int age,double m,const char* s);//带有参数的构造函数 Person(const Person & s);//定义复制构造函数 Person & operator=(const Person &p);//重载=操作符,实现深度复制 virtual ~Person();//析构函数 virtual void playway();//定义一个虚函数,通过虚函数实现多态 void GetName(); void SetPerson(int id, std: