析构函数

Effective c++学习笔记——条款08:别让异常逃离析构函数

隐身守侯 提交于 2019-12-07 07:39:36
Prevent exceptions from leaving destructors 本条款主要讲述当我们写代码的时候,如果出现了异常,让我们如何对异常处理,如何更加安全的处理异常。让我们的代码看起来更加完美。 1、 问题来源 案例1 由于C++并不禁止析构函数吐出异常,但它并不鼓励你这么做,所以,当我们不小心写出了问题代码的时候。考虑下面的代码: c++并不禁止析构函数吐出异常,但它并不鼓励你这么做。考虑下面的代码: class Widget { public: ~Widget(){...} //假设这个可能吐出一个异常 }; void dosomething() { vector<Widget> v; } //v在这里被自动销毁 当vector被销毁,它有责任销毁其内含的所有Widgets。假设v内含十个Widgets,而在析构第一个元素期间,有个异常被抛出。其他九个widgets还是应该被销毁,因此v应该调用它们各个析构函数。但假设在那些调用期间,第二个widget析构函数又抛出异常。现在有两个同时作用的异常,这对c++而言太多了。 在两个异常同时存在的情况下,程序若不是结束执行就是导致不明确行为。本例中会导致不明确的行为。使用标准程序库的任何其他容器或TR1的任何容器或甚至array,也会出现相同情况。容器或array并非遇上麻烦的必要条件,只要析构函数吐出异常

构造函数与析构函数的调用时间

怎甘沉沦 提交于 2019-12-07 07:39:24
构造函数与析构函数是被编译器隐式调用的。这些函数的调用时间取决于程序执行进入和离开实例化对象的作用域的顺序。通常,析构函数的调用顺序和对应构造函数的调用顺序相反。但是,对象的存储类别可以改变析构函数的调用顺序。 在全局作用域内定义的构造函数在该文件中任何其他函数(包括main函数)开始执行之前执行(尽管文件间的构造函数的执行顺序是不确定的)。在main函数终止时,调用相应的析构函数。exit函数强制程序立即终止并且不执行自动对象的析构函数。该函数常用于在检测到输入错误或打不开要处理的文件时终止程序。abort函数类似于exit函数,但它强制程序立即终止,不允许调用任何对象的析构函数。abort通常用于指示程序的异常中断。 自动局部对象的构造函数在执行到达对应的程序点时调用,对应的析构函数在对象离开该对象所在的作用域时(即定义该对象的执行结束时)调用。自动局部对象的构造函数和析构函数在每次到达和离开该对象的作用域时调用。如果程序使用exit和abort函数终止,则不调用自动对象的析构函数。 static局部对象的构造函数只在执行第一次到达定义对象的程序点时调用一次。对应的析构函数在main函数终止或调用exit函数时调用。全局和static对象的释放顺序和创建顺序相反。如果遇到调用abort函数终止程序,则不调用static对象的析构函数。 来源: CSDN 作者: 悠然见南山-

面向对象——构造函数与析构函数(多语言比较——整合自网络)

心已入冬 提交于 2019-12-07 07:39:10
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 我们在创建和销毁对象时需要执行一些任务。例如,在创建对象时给属性赋值,在对象销毁时关闭数据连接等,这时就需要构造函数和析构函数。 c++ 包含 构造函数 和析构函数的C++程序。 #include<string> #include<iostream> usingnamespacestd; classstud //声明一个类 { private : //私有部分 intnum; charname[10]; charsex; public : //公用部分 stud(intn,charnam[],chars) //构造函数 { num=n; strcpy (name,nam); sex=s; } ~stud() //析构函数 { cout<< "studhasbeendestructed!" <<endl; //通过输出提示告诉我们析构函数确实被调用了 } voiddisplay() //成员函数,输出对象的数据 { cout<< "num:" <<num<<endl; cout<< "name:" <<name<<endl;

php面向对象之构造函数和析构函数

浪子不回头ぞ 提交于 2019-12-07 07:38:57
php面向对象之构造函数和析构函数 简介 php面向对象支持两种形式的构造函数和析构函数,一种是和类同名的构造函数(php5.5之前),一类是魔术方法(php5.5之后)。与类名相同的构造函数优先级比魔术方法低。 php有一类很神奇的方法,这些方法是保留方法,通常不会在外部被显式调用,他们使用双下划线(__)开头,他们被称为魔术方法(Magic Methods)。php官方也不建议定义其他双下划线开头的方法。 这次介绍最常见的魔术方法:构造函数和析构函数。 1. 构造函数(__construct) void __construct ([ mixed $args [, $... ]] ) 构造函数:拥有构造函数的类会在每次创建新对象时先调用此方法,所以非常适合在使用对象前做一些初始化服务。 注意:   1. clone并不会调用构造函数    2. 如果子类定义了构造函数,则不会隐式调用父类的构造函数   3. 子类的构造函数允许和父类的构造函数参数不一致   4. 如果子类没有定义构造函数,php会尝试寻找父类的构造函数   5. 如果父类没有定义构造函数,使用parent关键字显式调用父类构造函数,会导致致命错误 1 <?php 2 3 class P{ 4 5 public function __construct(){ 6 echo __CLASS__ . "\n"; 7 }

C++中的构造函数和析构函数

一曲冷凌霜 提交于 2019-12-07 07:38:42
c++程序中的初始化和清理工作,分别由两个特殊成员函数来完成,他们就是构造函数和析构函数。 构造函数 c++是一种面向对象的编程语言,它要让程序员使用类对象就像使用标准类型一样。 比如要你写一个函数,它的功能就好像int、char一样,能初始化一个Clock类对象,并且能将值赋给它的数据成员。而构造函数就可以定义这么一个对象,还可以同时对它的数据成员赋初值。 构造函数的作用就是在对象被创建时利用特定值构造一个对象,将对象初始化为一个特定状态。此外,它还有两个特殊性质: - 构造函数的函数名和类名相同,且没有返回值 - 构造函数通常被声明为公有函数 #include<iostream> using namespace std ; class Clock{ public : Clock( int newH, int newM, int newS); //构造函数 void setTime( int newH, int newM, int newS); void showTime(); private : int hour, minute, second; }; void Clock::setTime( int newH, int newM, int newS){ hour=newH; minute=newM; second=newS; } void Clock::showTime(){

实验三 构造函数与析构函数

不羁岁月 提交于 2019-12-07 07:37:53
实验目的和要求 熟悉类的定义格式和类中成员的访问权限。 构造函数与析构函数的调用时机与顺序。 掌握对象的定义以及对象的初始化的时机与方法。 实验内容 1. 下面程序sy3_1.cpp中用ERROR标明的语句有错,在不删除和增加代码行的情况下,改正错误语句,使其正确运行。 //sy_1.cpp #include<iostream> using namespace std ; class Aa { public : Aa( int i= 0 ){a=i; cout << "Constructor" <<a<<endl;} ~Aa(){ cout << "Destructor" <<a<<endl;} void print(){ cout <<a<<endl;} private : int a; }; int main() { Aa a1( 1 ),a2( 2 ); a1.print(); //cout<<a2.a<<endl; //ERROR a2.print(); return 0 ; } 源程序已被注释。添加修改后程序。 运行结果 结果分析: a是私有数据。所以main函数不能访问并输出 a2.a 。所以改为 a2.print() 。 该程序中定义了两个对象a1和a2。类中有两个构造函数。a1用成员选择运算符“ . ”访问成员函数 print() 。 创建对象a1

C++类的构造函数和析构函数

不羁的心 提交于 2019-12-07 07:37:22
C++类的构造函数和析构函数 1. 构造函数的使用方式 2. 构造函数、析构函数的调用顺序 C++类的构造函数和析构函数是两个很重要的函数,下面分别进行介绍。 1. 构造函数的使用方式 构造函数的使用方式有两种:初始(值)列、赋值,使用方式如下程序中所写: class complex { public : complex ( double r = 0 , double i = 0 ) : re ( r ) , im ( i ) { } //初始(值)列 //complex (double r = 0,double i = 0) { re = r; im = i; } //赋值 . . . private : double re , im ; } 推荐使用初始(值)列的方式,而不使用在构造函数函数体内进行赋值操作。 为什么呢? 首先,我们需要明确的通过类构造对象的过程是: 第一步,初始化对象; 第二步,对这个对象的数据进行赋值。 而初始(值)列的方式是在第一步完成的,在构造函数函数体内进行赋值是在第二步完成的,所以使用初始(值)列的方式可以少一步操作,所以更加推荐使用。 如果不希望外界定义这个类的对象,可以把构造函数放在private区域。代码如下: class A { public : static A & getInstance ( ) ; setup ( ) { . . . }

构造函数与析构函数中不调用虚函数

僤鯓⒐⒋嵵緔 提交于 2019-12-07 07:37:13
本文参考《effective C++》第九条款 在C++中,提倡不能在构造函数和析构函数中调用虚函数。 这是为什么呢? 首先,我们先回顾一下C++虚函数的作用。 虚函数的引入是c++运行时多态的体现,通过调用虚函数可以在运行程序时实现动态绑定,体现了面向对象编程多态的思想。 那为何提倡不能在构造函数与析构函数中不能调用虚函数。接下来我们通过代码分析在构造函数或者虚构函数中调用虚函数是否可行。 假设我们有两种商品A, B。 我们要记录着两种商品的销售记录,每当销售一种商品时,我们就要记录下来。 class item { public: item(); virtual void saleRecord() const= 0 ; //销售记录,纯虚函数 ... }; item::item() { ... virtual void saleRecord(); ... } class itemA : public item { public: itemA(); virtual void saleRecord(); ... }; class itemB : public item { public: itemB(); virtual void saleRecord(); ... }; 我们执行如下代码: itemB b; 一个derived class B 对象会被创建,

python---面向对象,class定义、构造函数、析构函数、基本继承

徘徊边缘 提交于 2019-12-07 07:36:57
python—面向对象,class定义、构造函数、析构函数、基本继承 进阶课 面向对象 1.class的基本定义 2.构造,析构函数 注意:在class类里面函数的参数第一个值必须是self,意思是指向对象本身的 1. class的基本定义 >>> class test(object): ... a = 1 #a被称为test类的属性 ... def func1(self): #func1被称为test类的方法 ... pass ... >>> >>> t = test() #实例化 >>> print t.a #调用属性 1 >>> print t.func1() #调用方法 None >>> # 我们所有的class都是object的派生类 2. 构造,析构函数 1 )构造函数(__init__称为class的构造函数与构造方法,一般做为t实例化设置初始值而存在的。即一般是为了初始化对象时将必须要用到的属性、方法做一些定义,而存在的) >>> class test(object): ... def __init__(self,arg1,arg2): #构造函数 ... self.arg1 = arg1 #对arg1进行初始的赋值,因此把arg1引入到test类的内部中 ... self.arg2 = arg2 #对arg2进行初始的赋值,因此把arg2引入到test类的内部中

C/C++——构造函数和析构函数

こ雲淡風輕ζ 提交于 2019-12-07 07:36:47
本文对类的构造函数和析构函数进行总结,主要包括了构造函数的初始化、重载、使用参数和默认参数,拷贝构造函数和析构函数,希望能帮助读者在程序开发中更好的理解类,属 于 C/C++ 基础。 1、 构造函数 构造函数与类名相同,它是一种特殊的成员函数,没有返回值类型和返回值。在对象建立时自动调用,不需要也不能由用户调用。构造函数主要为对象开辟内存空间,完成对象数据成员的初始化。 (1) 、构造函数的初始化 构造函数的主要功能是给对象初始化,初始化有两种方式,一种是用参数初始化列表,这种方式简练;另一种是在构造函数的函数体内对数据成员进行赋值实现初始化,这种方式方便直观。 参数初始化列表初始化 参数初始化列表初始化的形式是在函数的首部的末尾加冒号,然后列出用逗号分隔的数据成员列表初始化表。如: T ::T( int a , int b ) :hour( a ),minute( b ) {} 表示用a初始化hour,用b初始化minute,即 hour=a; minute=b; 虽然后面的花括号是空的,但已经给对象进行了初始化。 注意: ① 对于 const 或引用类型的成员必须在构造函数初始化列表中进行初始化,这是初始化它们的唯一机会, 原因分析在赋值语句初始化段。 ② 不能用参数初始化列表对静态数据成员初始化,而且只能在类外初始化 ,可以像普通数据成员那样通过对象访问,也可以通过类名访问