c 中构造函数和析构函数讲解

合集下载

结构体构造函数与析构函数

结构体构造函数与析构函数

结构体构造函数与析构函数结构体是C++程序开发中常用的一种数据类型,可以将不同的数据类型封装在一个结构体中,以便于更好地组织和管理数据,提高程序的可读性和可维护性。

在结构体中,构造函数和析构函数是很重要的成员函数之一,它们分别用于完成结构体对象的初始化和销毁操作,下面我们来具体了解一下。

一、什么是结构体构造函数?结构体构造函数是一种特殊的成员函数,用于在定义结构体对象时自动执行,来完成一些对象的初始化操作。

它的特点如下:1、构造函数名称与结构体名称一致。

2、不能有返回值,包括void也不行。

3、可以有参数列表,但不能有默认参数。

4、可以有多个重载的构造函数。

5、如果没有显式定义构造函数,则编译器会自动生成默认构造函数。

例如:struct Student{int num;char name[20];float score;Student()//默认构造函数{num = 0;strcpy(name, "No name");score = 0.0;cout << "Constructor is called." << endl;}Student(int n, char na[], float s)//重载构造函数{num = n;strcpy(name, na);score = s;cout << "Another constructor is called." << endl;}};int main(){Student s1;//调用默认构造函数Student s2(1001, "Jack", 80.5);//调用有参构造函数return 0;}在上面的代码中,我们定义了一个名为Student的结构体,它有两个构造函数:默认构造函数和重载构造函数。

在main函数中,我们分别定义了两个结构体对象s1和s2,并使用不同的方式调用了它们的构造函数。

C++_构造函数与析构函数

C++_构造函数与析构函数

C++_构造函数与析构函数构造函数与析构函数1 构造函数1.1 构造函数具有⼀些特殊的性质1.2 定义构造函数的⼀般形式1.3 利⽤构造函数创建对象2 成员初始化表3 缺省参数的构造函数4 重载构造函数5 拷贝构造函数5.1 ⾃定义拷贝构造函数5.2 缺省的拷贝构造函数5.3 调⽤拷贝构造函数的三种情况5.4 浅拷贝和深拷贝6 析构函数7 调⽤构造函数和析构函数的顺序8 对象的⽣存期构造函数和析构函数都是类的成员函数,但它们都是特殊的成员函数,执⾏特殊的功能,不⽤调⽤便⾃动执⾏,⽽且这些函数的名字与类的名字有关。

C++语⾔中有⼀些成员函数性质是特殊的,这些成员函数负责对象的建⽴、删除。

这些函数的特殊性在于可以由编译器⾃动地隐含调⽤,其中⼀些函数调⽤格式采⽤运算符函数重载的语法。

C++引进⼀个⾃动完成对象初始化过程的机制,这就是类的构造函数。

对象的初始化1. 数据成员是不能在声明类时初始化2. 类型对象的初始化⽅法:1. 调⽤对外接⼝(public成员函数)实现:声明类→定义对象→调⽤接⼝给成员赋值2. 应⽤构造函数(constructor)实现:声明类→定义对象→同时给成员赋值1. 构造函数构造函数是⼀种特殊的成员函数,它主要⽤于为对象分配空间,进⾏初始化。

1.1 构造函数具有⼀些特殊的性质:(1) 构造函数的名字必须与类名相同。

(2) 构造函数可以有任意类型的参数,但不能指定返回类型。

它有隐含的返回值,该值由系统内部使⽤。

(3) 构造函数是特殊的成员函数,函数体可写在类体内,也可写在类体外。

(4) 构造函数可以重载,即⼀个类中可以定义多个参数个数或参数类型不同的构造函数。

构造函数是不能继承(5) 构造函数被声明为公有函数,但它不能像其他成员函数那样被显式地调⽤,它是在定义对象的同时被调⽤的。

(6) 在声明类时如果没有定义类的构造函数,编译系统就会在编译时⾃动⽣成⼀个默认形式的构造函数,(7) 默认构造函数是构造对象时不提供参数的构造函数。

C++基抽象类的构造析构(纯)虚函数

C++基抽象类的构造析构(纯)虚函数

C++基抽象类的构造析构(纯)虚函数⼀、析构函数可定义为⼀、析构函数可定义为纯虚函数纯虚函数,但也必须给出函数定义,但也必须给出函数定义 Effective C++ 条歀07: 为多态基类声明virtual 析构函数(Declare destructors virtual in polymorphic base classes ) 在某些类⾥声明纯虚析构函数很⽅便。

纯虚函数将产⽣抽象类——不能实例化的类(即不能创建此类型的对象)。

有些时候,你想使⼀个类成为抽象类,但刚好⼜没有任何纯虚函数。

怎么办?因为抽象类是准备被⽤做基类的,基类必须要有⼀个虚析构函数,纯虚函数会产⽣抽象类,所以⽅法很简单:在想要成为抽象类的类⾥声明⼀个纯虚析构函数。

1 //这⾥是⼀个例⼦:2 class awov {3 public :4 virtual ~awov() = 0; // 声明⼀个纯虚析构函数5 }; 这个类有⼀个纯虚函数,所以它是抽象的,⽽且它有⼀个虚析构函数,所以不会产⽣析构函数问题。

但这⾥还有⼀件事:必须提供纯虚析构函数的定义: awov::~awov() { ... } // 纯虚析构函数的定义 这个定义是必需的,因为虚析构函数⼯作的⽅式是:最底层的派⽣类的析构函数最先被调⽤,然后各个基类的析构函数被调⽤。

这就是说,即使是抽象类,编译器也要产⽣对~awov 的调⽤,所以要保证为它提供函数体。

如果不这么做,链接器就会检测出来,最后还是得回去把它添上。

⼆、? 关于C++为什么不⽀持虚拟构造函数,Bjarne 很早以前就在C++Style and Technique FAQ ⾥⾯做过回答 Avirtual call is a mechanism to get work done given partialinformation. In particular, "virtual" allows us to call afunction knowing only an interfaces and not the exact type of theobject. To create an object you need complete information.Inparticular, you need to know the exact type of what you want tocreate. Consequently, a "call to a constructor" cannot bevirtual. 含义⼤概是这样的:虚函数调⽤是在部分信息下完成⼯作的机制,允许我们只知道接⼝⽽不知道对象的确切类型。

C++在单继承、多继承、虚继承时,构造函数、复制构造函数、赋值操作符、析构函数的执行顺序和执行内容

C++在单继承、多继承、虚继承时,构造函数、复制构造函数、赋值操作符、析构函数的执行顺序和执行内容

C++在单继承、多继承、虚继承时,构造函数、复制构造函数、赋值操作符、析构函数的执⾏顺序和执⾏内容⼀、本⽂⽬的与说明1. 本⽂⽬的:理清在各种继承时,构造函数、复制构造函数、赋值操作符、析构函数的执⾏顺序和执⾏内容。

2. 说明:虽然复制构造函数属于构造函数的⼀种,有共同的地⽅,但是也具有⼀定的特殊性,所以在总结它的性质时将它单独列出来了。

3. 单继承、多继承、虚继承,既然都属于继承,那么虽然有⼀定的区别,但还是相同点⽐较多。

如果放在⼀块讲,但为了将内容制作成递进的,就分开了,对相同点进⾏重复,(⼤量的复制粘贴哈),但在不同点进⾏了标注。

注意:三块内容是逐步递进的如果你懂虚函数,那么单继承和多继承那块你就可以不看;如果你懂多继承,那单继承你就不要看了,⾄于虚继承就等你懂虚继承再回来看吧;如果你只懂单继承,那你就只看单继承就好。

⼆、基本知识1. 对于⼀个空类,例如:class EmptyClass{};虽然你没有声明任何函数,但是编译器会⾃动为你提供上⾯这四个⽅法。

class EmptyClass {public:EmptyClass(); // 默认构造函数EmptyClass(const EmptyClass &rhs); // 复制构造函数~EmptyClass(); // 析构函数EmptyClass& operator=(const EmptyClass &rhs); // 赋值运算符}对于这四个⽅法的任何⼀个,你的类如果没有声明,那么编译器就会⾃动为你对应的提供⼀个默认的(注意合成默认构造函数是⽤于没有编写构造函数编译器才会合成默认构造函数,其中复制构造函数也是构造函数)。

(在《C++ primer》中,这个编译器⾃动提供的版本叫做“合成的***”,例如合成的复制构造函数)当然如果你显式声明了,编译器就不会再提供相应的⽅法。

2. 合成的默认构造函数执⾏内容:如果有⽗类,就先调⽤⽗类的默认构造函数。

构造函数和析构函数总论

构造函数和析构函数总论

对于相同域中的对象:先构造的后析构,后构造的先 析构。
静态(static)类成员
一、静态数据成员 1、定义: class CTest { public ; static int count ; ┆ }; CTest rect1,rect2,… //定义多个对象 注: 无论生成多少个CTest对象,只有一个count,因此它是由 所有CTest对象共有的。静态数据成员只存储一处,供所有 对象共用。静态数据成员能够实现多个对象的数据共享。
构造函数和析构函数总论
在类中可以定义两个指定功能成员函数: 构造函数 析构函数 一、 构造函数 用来生成对象,可以初始化对象的数据成 员,构造函数在有对象生成时有系统自动调用。
class crectangle { private : int left ; int right ; public : crectangle( int L, int R) //构造函数 {left=L; right=R ;} void getcoord ( int *L , int *R ) {*L=left ; *R = right } };
const对象和const成员函数
①对象定义中加入const,表示该对象为常对象, 常对象中的数据成员为常变量,不能改变该类 中任何数据成员的值,数据成员必须有初值。 常对象用来保护对象中的数据不被修改; ②类中的函数定义中加入const,表示该函数为 常成员函数,只能引用本类中的数据成员,而 不能不能改变它们。常对象只允许调用常函数。 ③类中的数据成员定义中加入const,表示该数据 成员为常数据成员,其值是不能改变的,只能 通过构造函数的成员初始化表对其进行初始化。
二.析构函数
1 、析构函数:用来释放对象,在对象 删除前,用它来做一些清理工作,它在 类对象销毁时自动调用。

C语言里面构造函数和析构函数的运用办法

C语言里面构造函数和析构函数的运用办法

C语言里面构造函数和析构函数的运用办法C语言里面构造函数和析构函数的运用办法摘要:构造函数与析构函数是一个类中看似较为简单的两类函数,但在实际运用过程中总会出现一些意想不到的运行错误。

本文将较系统的介绍构造函数与析构函数的原理及在C#中的运用,以及在使用过程中需要注意的若干事项。

关键字:构造函数;析构函数;垃圾回收器;非托管资源;托管资源一.构造函数与析构函数的原理作为比C更先进的语言,C#提供了更好的机制来增强程序的安全性。

C#编译器具有严格的类型安全检查功能,它几乎能找出程序中所有的语法问题,这的确帮了程序员的大忙。

但是程序通过了编译检查并不表示错误已经不存在了,在“错误”的大家庭里,“语法错误”的地位只能算是冰山一角。

级别高的错误通常隐藏得很深,不容易发现。

根据经验,不少难以察觉的程序错误是由于变量没有被正确初始化或清除造成的,而初始化和清除工作很容易被人遗忘。

微软利用面向对象的概念在设计C#语言时充分考虑了这个问题并很好地予以解决:把对象的初始化工作放在构造函数中,把清除工作放在析构函数中。

当对象被创建时,构造函数被自动执行。

当对象消亡时,析构函数被自动执行。

这样就不用担心忘记对象的初始化和清除工作。

二.构造函数在C#中的运用构造函数的名字不能随便起,必须让编译器认得出才可以被自动执行。

它的命名方法既简单又合理:让构造函数与类同名。

除了名字外,构造函数的另一个特别之处是没有返回值类型,这与返回值类型为void的函数不同。

如果它有返回值类型,那么编译器将不知所措。

在你可以访问一个类的方法、属性或任何其它东西之前,第一条执行的语句是包含有相应类的构造函数。

甚至你自己不写一个构造函数,也会有一个缺省构造函数提供给你。

class TestClass{public TestClass(): base() {} // 由CLR提供}下面列举了几种类型的构造函数1)缺省构造函数class TestClass{public TestClass(): base() {}}上面已介绍,它由系统(CLR)提供。

gcc 函数名修饰

gcc 函数名修饰

gcc 函数名修饰gcc(GNU Compiler Collection)是一个广泛使用的开源编译器套件,在C/C++编程领域有着非常高的知名度和应用率。

在使用gcc编译C/C++代码时,我们经常会遇到一个诸多困扰开发者的问题——函数名修饰。

对于初学者来说,理解函数名修饰的作用和原理是很有必要的。

本文将就此问题进行讲解。

一、什么是函数名修饰函数名修饰,也称为函数名重载,是指在编译阶段,编译器将函数名与参数列表一起编码成一个新的函数名,这种方法称为函数名修饰。

在C++中,函数多态性和函数重载(overloading)特性的实现就与函数名修饰密不可分。

而在C语言中,虽然不支持函数重载,但是编译器仍会对函数名进行修饰。

例如,在C++中,有如下几个函数:```cppvoid func(int a, int b) {}void func(double a, double b) {}void func(char a, char b) {}```这几个函数的函数名都是“func”,但是参数列表却是不同的。

为了能够区分不同的函数,编译器就采用了函数名修饰的方法将这几个函数名进行区分,生成了不同的函数名。

二、为什么要进行函数名修饰在很多编程语言中,函数的名称是可以相同的,但是函数的参数列表必须是不同的,通过函数名修饰可以实现不同名但参数列表相同的函数。

这种技术也是实现C++重载和多态这两个强大特性的核心机制。

从另一个角度来说,由于函数名中包含函数参数信息,所以也会在一定程度上增加代码安全性。

例如,在C++中,我们可以使用重载的方法实现不同类型的加法运算:```cppint add(int a, int b) { return a + b; }double add(double a, double b) { return a + b; }```这就是通过函数名修饰实现重载的一个例子。

三、如何禁用函数名修饰在某些情况下,我们需要禁用函数名修饰,以方便直接使用函数的原名称,如C语言中的一些库函数。

c++程序设计教程 第十章 构造函数和析构函数

c++程序设计教程 第十章 构造函数和析构函数

10.1.2 构造函数重载
在一个类中可以定义多个构造函数,以便对类 对象提供不同的初始化方法。这些构造函数的函数 名完全相同,都没有返回值,而参数的类型或参数 的个数各不相同。对于一般的重载函数,系统是根 据参数列表来决定调用哪个函数,对重载的构造函 数而言,系统是根据创建对象时提供的参数来确定 调用哪个构造函数来初始化对象的。
return s;
4
}
2.使用参数初始化列表的构造函数
使用参数初始化列表的构造函数的形式为:
类名::构造函数名(<形参1,形参2,……>)<:数据成员1(形参1),数据成员2(形参2 ),………>
{函数体} 例10.1 中定义类Tri 的构造函数可以写成如下形式:
Tri(double x , double y , double z ):a(x),b(y),c(z){}
return s;
cout<<"Tria的周长"<<Tria.Peri()<<endl;
}
cout<<"tria的面积为: "<<tria.Area()<<endl;
};
}
7
10.1.3 默认的构造函数
默认的构造函数又称缺省的构造函数,有两种形式:
(1)参数为缺省值的构造函数,如在类体中说明以下形式 的构造函数:
函数,并不是用函数名调用的,而是隐式调用的
2
定义构造函数的两种方法
构造函数有不带参数的和带参数的两种,其定义的 形式都是一致的。 1.在构造函数体内对数据成员赋值: 在类体中定义构造函数的形式如下: 类名(<形参1,形参2,……>) {函数体} 其中,尖括号< >中的内容可以省略。
  1. 1、下载文档前请自行甄别文档内容的完整性,平台不提供额外的编辑、内容补充、找答案等附加服务。
  2. 2、"仅部分预览"的文档,不可在线预览部分如存在完整性等问题,可反馈申请退款(可完整预览的文档不适用该条件!)。
  3. 3、如文档侵犯您的权益,请联系客服反馈,我们会尽快为您处理(人工客服工作时间:9:00-18:30)。

10.1 构造函数
2. 用new为指针成员分配动态空间 当类的数据成员为指针时,在构造函数中应: ·先用new运算符为指针动态分配空间; ·然后再对指针所指空间赋值。
如: class Array { int*p; ...}; //p表示10个元素的一维数组 则如下的构造函数都是错误的: Array(int *t){p=t;} Array (int *t){*p=*t;} Array (int *t){for(int i=0;i<10;i++)p[i]=t[i];} Array (int *t){p=new int[10]; p=t;} // *p=*t; 正确的应为: Array (int *t){ p=new int[10]; // 分配动态空间 for(int i=0;i<10;i++)p[i]=t[i]; // 对动态空间赋值 }
Visual C++程序设计
第10章
构造函数 和析构函数
第10章 构造函数和析构函数
10.1 构造函数 10.2 析构函数 10.3 实现类型转换和 拷贝的构造函数
10.4 构造函数和对象成员
10.1 构造函数
给对象的数据成员赋值有二类(四种)方法: 1. 定义时赋值(初始化) (1)用数据列表初始化(数据成员为公有访问权限); (2)用构造函数初始化。
10.1 构造函数
10.1.1 构造函数的概念 1. 构造函数是实现数据成员初始化的特殊的成员函数; 2. 构造函数与类同名,没有类型,也不返回值; 3. 创建对象时,构造函数被自动调用。每创建一个对象 都必须调用一次构造函数,每调用一次构造函数必定创 建一个对象。 10.1.2 构造函数的种类 1. 普通构造函数:普通参数; 2. 拷贝构造函数:参数为对象的引用。 一个类至少有上述两个构造函数,可以有更多的构造 函数(构造函数允许重载),以实现不同形式对象的创 建。
2. 定义后赋值 (1)用成员函数赋值----回顾第9章示例3; (2)用同类型的对象赋值。 如:class A{ public: int a,b; void set(int x,int y){a=x;b=y;} }; void main() { A a1={5,10},a2,a3; a2.set(15,20); a3=a1;}
class Point{ float x,y; public: Point(float a,float b); Point(float a) { x=y=a;} void print() { cout<<‘(‘<<x<<‘,’<<y<<“)\n”; } }; Point:: Point(float a,float b) { x=a; y=b; }
10.1 构造函数
10.1.4 构造函数产生对象 建立对象时,必须提供与构造函数形参一致的实参,其 基本格式只有如下两种形式:
类名 对象名(实参); 类名 对象名; 例10-2 用例10-1定义的类定义对象,并初始化。 class Point{ 主函数中,能否添加下列语句: float x,y; Point p3; public: Point(float a,float b); Point(float a) { x=y=a;} void print(){ cout<<‘(‘<<x<<‘,’<<y<<“)\n”; } }; Point:: Point(float a,float b) { x=a; y=b; } void main(){ Point p1(5),p2(10,15); p1.print();p2.print(); }
10.1 构造函数
10.1.3 构造函数的定义
1. 类中定义格式 类名(形参列表) { ... } //函数体,对数据成员赋值 2. 类中说明,类外定义
(1) 类中说明
类名(形参列表); (2)类外定义 类名::类名(形参列表) { ... } //函数体
10.1 构造函数
例10-1 定义表示平面点的类Point及其构造函数。
10.1 构造函数
10.1.5 缺省的构造函数
1. 缺省构造函数的种类 (1)系统自动产生的构造函数,如下所示: 类名(){ } (2)用户定义的没有参数的构造函数; (3)用户定义的所有参数都有缺省值的构造函数。
2. 用缺省构造函数创建对象的格式:类名 对象名;
3. 使用时的注意 (1)只有在用户没有定义构造函数时,系统才自动产 生构造函数; (2)类中可能没有缺省的构造函数; (3)一个类最多只能有一个缺省的构造函数。
10.1 构造函数
例10-3 缺省构造函数的使用。 class Point{ float x,y; 能否对A行作如下修改? public: Point( ) { x=0; y=0; } Point(float a =0 ,float b =0 ) { x=a; y=b; }//A void print(){ cout<<‘(‘<<x<<‘,’<<y<<“)\n”; } };
void main() { PoinБайду номын сангаас p1 , p2(1,2); p1.print(); p2.print(); } 主函数能否增加: Point p3(); p3.print();
10.1 构造函数
10.1.6 构造函数和new运算符
1. 用new运行符产生动态对象 (1)产生单个对象(可以初始化); (2)产生数组对象(不能初始化)。 如: class C { float r,i; public: C (float r1 ,float i1){ r=r1; i=i1; cout<<“构造\n”; } C (){ r=i=0; cout<<“缺省构造\n”; } }; void main() { C *p1=new C,*p2=new C (2,-3), *p3=new C[5]; }
10.2 析构函数
1. 析构函数的概念 用于撤消对象的成员函数。
2. 定义格式 (1)类中定义 ~类名() { ... } //函数体 (2)类中说明,类外定义 ① 类中说明 ~类名();//类中说明 ② 类外定义 类名::~类名()//类外定义 { ... } //函数体
相关文档
最新文档