课题:c++类的构造函数详解
- 格式:doc
- 大小:58.50 KB
- 文档页数:7
C语言里面构造函数和析构函数的运用办法C语言是一种面向过程的编程语言,没有类的概念,因此并不存在构造函数和析构函数的概念。
构造函数是在对象创建时被自动调用的特殊函数,用于初始化对象的成员变量。
析构函数是在对象销毁时自动调用的特殊函数,用于清理对象所占用的资源。
不过,虽然C语言本身没有构造函数和析构函数的语法支持,但可以通过编码技巧模拟实现一些类似的功能。
构造函数的作用是在创建对象时进行必要的初始化操作,一般包括为成员变量分配内存空间,初始化成员变量的值等。
在C语言中,可以通过在函数内定义一个结构体变量并将其指针返回,来实现类似构造函数的功能。
例如,以下代码演示了一个简单的"Person"结构体,包含姓名和年龄两个成员变量以及初始化和打印信息的函数。
```c#include <stdio.h>#include <stdlib.h>#include <string.h>typedef structchar name[20];int age;} Person;Person* createPerson(const char* name, int age)Person* p = (Person*) malloc(sizeof(Person));strcpy(p->name, name);p->age = age;return p;void printPerson(Person* p)printf("Name: %s, Age: %d\n", p->name, p->age);int maiPerson* p = createPerson("John", 25);printPerson(p);free(p); // 在不需要对象时,需要手动释放内存return 0;```上述代码中,createPerson函数实现了一个类似构造函数的功能,通过动态分配内存来创建一个结构体对象,并将参数拷贝到对应的成员变量中。
c构造函数和析构函数C++是一门面向对象的编程语言,它支持类和对象的概念。
类是一种用户自定义的数据类型,它可以封装数据和函数,提供一种抽象的数据类型。
对象是类的实例,它具有类定义的属性和行为。
在 C++ 中,构造函数和析构函数是类的特殊成员函数,它们分别用于初始化对象和清理对象。
本文将详细介绍 C++ 构造函数和析构函数的概念、语法和使用方法。
一、构造函数1. 概念构造函数是一种特殊的成员函数,它在对象创建时自动调用,用于初始化对象的数据成员。
构造函数的名称必须与类名相同,没有返回值,也不允许有 return 语句。
2. 语法构造函数有以下几种语法:(1)默认构造函数如果一个类没有定义任何构造函数,编译器会自动生成一个默认构造函数,它没有任何参数,也没有任何语句。
默认构造函数的作用是初始化对象的数据成员。
例如:```class Person {public:string name;int age;};```上面的代码中,Person 类没有定义任何构造函数,因此编译器会自动生成一个默认构造函数。
(2)带参数构造函数如果一个类需要根据不同的参数创建对象,就需要定义带参数的构造函数。
带参数的构造函数可以有多个,它们的参数列表可以不同,但是名称必须相同。
例如:```class Person {public:Person(string name, int age) {this->name = name;this->age = age;}string name;int age;};```上面的代码中,Person 类定义了一个带参数的构造函数,用于根据姓名和年龄创建对象。
(3)拷贝构造函数拷贝构造函数是一种特殊的构造函数,用于用一个对象初始化另一个对象。
拷贝构造函数的参数必须是一个同类对象的引用。
例如:```class Person {public:Person(const Person& p) {this->name = ;this->age = p.age;}string name;int age;};```上面的代码中,Person 类定义了一个拷贝构造函数,用于用一个 Person 对象初始化另一个 Person 对象。
C语言中的构造函数:让你的代码更生动有力对于C语言中的构造函数,很多初学者可能会感到比较陌生。
所以,本文将从基础开始,逐步介绍C语言中的构造函数,让大家更好地理解它的作用。
首先,我们需要知道,C语言并没有像其他面向对象语言那样有构造函数这个概念。
但是,在C语言中,我们可以通过一些技巧来实现构造函数的功能。
具体来说,我们可以在定义结构体时,为其添加一个初始化函数。
这个函数可以用来初始化结构体中的各个成员变量,从而达到构造函数的效果。
例如:struct a{int x;int y;void (*init)(struct a*);};void init_a(struct a* self){self->x = 0;self->y = 0;}在上面的代码中,我们定义了一个结构体a,其中包含了两个成员变量x和y,以及一个指针类型的函数init。
同时,我们还定义了一个名为init_a的函数,它的作用是初始化结构体a中的成员变量x和y。
在定义init_a函数时,我们将self指针作为参数,这个指针指向了要被初始化的结构体实例。
在init_a函数中,我们就可以通过self 指针来访问结构体实例中的成员变量,从而完成初始化的任务。
通过这种方式定义的初始化函数,我们就可以在创建结构体实例时,自动调用这个函数,实现构造函数的效果。
例如:struct a obj;obj.init = init_a;obj.init(&obj);在上面的代码中,我们创建了一个名为obj的结构体实例,并将init_a函数注册到了obj.init指针中,这样在调用obj.init(&obj)时,就会执行init_a函数,从而完成obj结构体实例的初始化。
通过上面的示例代码,我们可以看出,C语言中的构造函数虽然需要手动实现,但是通过一些技巧的组合,我们同样可以让我们的代码更加生动有力。
c构造函数和析构顺序
在C++中,构造函数和析构函数是类的两个特殊成员函数,用于在对象创建和销毁时执行特定的操作。
在类中,可以定义一个或多个构造函数和析构函数,它们的执行顺序是非常重要的。
构造函数的执行顺序如下:
1. 基类构造函数:如果当前类是派生类,则先执行基类的构造函数,按照继承顺序从上到下执行。
2. 成员对象构造函数:执行当前类中所有成员对象的构造函数,按照定义顺序从上到下执行。
3. 当前类构造函数:执行当前类自身的构造函数。
析构函数的执行顺序与构造函数相反,如下:
1. 当前类析构函数:先执行当前类自身的析构函数。
2. 成员对象析构函数:执行当前类中所有成员对象的析构函数,按照定义顺序从下到上执行。
3. 基类析构函数:如果当前类是派生类,则最后执行基类的析构函数,按照继承顺序从下到上执行。
需要注意的是,如果在构造函数中抛出了异常,则会导致对象创建失败,此时会按照相反的顺序执行析构函数,以释放已经分配的资源。
因此,在编写构造函数和析构函数时,应该遵循以下几个原则:
1. 构造函数应该尽可能简单,避免在其中执行复杂的操作。
2. 析构函数应该释放所有已经分配的资源,避免内存泄漏。
3. 构造函数和析构函数中应该避免抛出异常,以免导致程序异常终止。
4. 在构造函数中,应该尽可能避免调用虚函数,因为此时对象还没有完全构造完成,可能会导致未定义的行为。
5. 在析构函数中,应该避免调用虚函数,因为此时对象已经被销毁,虚函数的行为是未定义的。
总之,构造函数和析构函数的顺序是非常重要的,正确的执行顺序可以保证对象的正确创建和销毁,避免内存泄漏和未定义行为。
c 构造函数-回复什么是构造函数?构造函数是一种特殊类型的函数,它用于创建和初始化对象。
在C语言中,构造函数被用来初始化类的成员变量。
当声明一个类的对象时,构造函数会被自动调用,以便对对象的数据成员进行初始化。
构造函数的名称与类的名称相同,且没有任何返回类型。
构造函数的使用方法在C语言中,使用构造函数需要遵循一定的语法规则。
首先,在类的声明中定义构造函数的原型。
然后,在类的实现部分定义构造函数的具体实现。
最后,在创建类的对象时,构造函数会被自动调用。
构造函数的原型通常定义在类的声明部分,具有以下语法形式:ClassName(ArgumentList);其中,ClassName是类的名称,ArgumentList是构造函数的参数列表。
构造函数的实现通常定义在类的实现部分,具有以下语法形式:ClassName::ClassName(ArgumentList) {构造函数的具体实现}其中,ClassName是类的名称,ArgumentList是构造函数的参数列表。
构造函数的参数列表可以包含任意数量的参数,也可以为空。
当构造函数的参数列表为空时,我们称之为默认构造函数(Default Constructor)。
构造函数的调用在C语言中,构造函数是在创建对象时自动调用的。
当声明一个类的对象时,构造函数会被调用以初始化对象的成员变量。
例如,我们可以使用以下语法创建一个对象:ClassName ObjectName;当执行以上代码时,会自动调用ClassName类的构造函数来初始化ObjectName对象。
构造函数的重载在C语言中,我们可以重载构造函数,即定义多个具有不同参数列表的构造函数。
当创建对象时,编译器会根据传入的参数类型和数量来选择合适的构造函数。
这使得我们可以根据不同的情况来初始化对象的成员变量。
构造函数的重载示例:class ClassName {public:默认构造函数ClassName() {构造函数的具体实现}带参数的构造函数ClassName(int arg1, int arg2) {构造函数的具体实现}};在上述示例中,我们定义了一个默认构造函数和一个带参数的构造函数。
C++构造函数详解及显式调用构造函数c++类的构造函数详解一、构造函数是干什么的class Counter{public:// 类Counter的构造函数// 特点:以类名作为函数名,无返回类型Counter(){m_value = 0;}private:// 数据成员int m_value;}该类对象被创建时,编译系统对象分配内存空间,并自动调用该构造函数->由构造函数完成成员的初始化工作eg: Counter c1;编译系统为对象c1的每个数据成员(m_value)分配内存空间,并调用构造函数Counter( )自动地初始化对象c1的m_value值设置为0故:构造函数的作用:初始化对象的数据成员。
二、构造函数的种类class Complex{private :double m_real;double m_imag;public:// 无参数构造函数// 如果创建一个类你没有写任何构造函数,则系统会自动生成默认的无参构造函数,函数为空,什么都不做// 只要你写了一个下面的某一种构造函数,系统就不会再自动生成这样一个默认的构造函数,如果希望有一个这样的无参构造函数,则需要自己显示地写出来Complex(void){m_real = 0.0;m_imag = 0.0;}// 一般构造函数(也称重载构造函数)// 一般构造函数可以有各种参数形式,一个类可以有多个一般构造函数,前提是参数的个数或者类型不同(基于c++的重载函数原理)// 例如:你还可以写一个Complex( int num)的构造函数出来// 创建对象时根据传入的参数不同调用不同的构造函数Complex(double real, double imag){m_real = real;m_imag = imag;}// 复制构造函数(也称为拷贝构造函数)// 复制构造函数参数为类对象本身的引用,用于根据一个已存在的对象复制出一个新的该类的对象,一般在函数中会将已存在对象的数据成员的值复制一份到新创建的对象中// 若没有显示的写复制构造函数,则系统会默认创建一个复制构造函数,但当类中有指针成员时,由系统默认创建该复制构造函数会存在风险,具体原因请查询有关“浅拷贝” 、“深拷贝”的文章论述Complex(const Complex & c){// 将对象c中的数据成员值复制过来m_real = c.m_real;m_imag = c.m_imag;}// 类型转换构造函数,根据一个指定的类型的对象创建一个本类的对象,//需要注意的一点是,这个其实就是一般的构造函数,但是对于出现这种单参数的构造函数,C++会默认将参数对应的类型转换为该类类型,有时候这种隐私的转换是我们所不想要的,所以需要使用explicit来限制这种转换。
c语言结构体的构造函数C语言结构体的构造函数在C语言中,结构体是一种自定义的数据类型,它允许我们将不同类型的数据组合在一起,形成一个更复杂的数据结构。
结构体可以包含多个成员,每个成员可以是不同的数据类型,比如整型、字符型、浮点型等。
在使用结构体时,我们经常需要对其进行初始化,以便为结构体成员赋予初始值。
为了实现这一目的,我们可以使用结构体的构造函数。
构造函数是一种特殊的函数,它用于创建和初始化结构体对象。
在C语言中,我们可以通过定义一个具有相同名称的函数来模拟结构体的构造函数。
下面是一个示例:```c#include <stdio.h>// 定义一个结构体struct Student {char name[20];int age;float score;};// 定义结构体的构造函数void initStudent(struct Student *student, char *name, int age, float score) {strcpy(student->name, name);student->age = age;student->score = score;}int main() {// 创建结构体对象并初始化struct Student student;initStudent(&student, "张三", 18, 90.5);// 输出结构体对象的成员printf("姓名:%s\n", );printf("年龄:%d\n", student.age);printf("分数:%f\n", student.score);return 0;}```在上面的示例中,我们首先定义了一个结构体`Student`,它包含了三个成员:`name`、`age`和`score`。
然后我们定义了一个名为`initStudent`的函数,它的作用是初始化一个`Student`类型的对象。
c 构造函数-回复构造函数(Constructor)是一种特殊的函数,在面向对象编程中扮演着重要的角色。
它用于创建和初始化对象,确保对象在被使用前具备合适的初始状态。
本文将介绍构造函数的基本概念、特性和用法,以及如何编写自定义的构造函数。
一、构造函数的概念和特性构造函数是一种特殊的函数,它与类名相同,没有返回类型,且在创建对象时会被自动调用。
构造函数在对象创建时执行,负责为对象分配内存并初始化数据成员。
构造函数有以下几个特性:1. 构造函数与类名相同,不返回任何类型。
2. 构造函数在对象创建时自动调用,不需要手动调用。
3. 构造函数可以有多个重载版本,根据参数的不同进行选择性调用。
4. 默认情况下,如果没有定义构造函数,编译器会自动生成一个无参构造函数。
5. 可以在构造函数中初始化数据成员,创建对象时可以提供初始值。
二、构造函数的用途构造函数的主要用途是初始化对象的数据成员,确保对象在被使用之前具有正确的初始状态。
它可以执行以下操作:1. 分配内存空间:构造函数负责为对象分配内存空间,确保对象在创建时有足够的内存存储其数据成员。
2. 初始化数据成员:构造函数可以为对象的数据成员赋予初始值。
这样可以避免在对象创建后再手动初始化数据成员的麻烦。
3. 执行其他必要的操作:构造函数还可以执行其他必要的操作,如打开文件、建立数据库连接等。
三、构造函数的语法和使用方法构造函数的语法与普通函数类似,但没有返回类型。
以下是构造函数的基本语法:cclass MyClass {public:构造函数,与类名相同,没有返回类型MyClass() {构造函数的内容}};在创建对象时,会自动调用构造函数:cMyClass obj; 创建对象时调用构造函数可以为构造函数定义参数,以实现对对象的不同初始化方式:cclass MyClass {public:带参数的构造函数MyClass(int value) {构造函数的内容}};创建对象时,可以传递参数:cMyClass obj(42); 创建对象并传递参数四、自定义构造函数除了编译器提供的默认构造函数外,我们还可以自定义构造函数以满足特定需求。
构造函数详解,explicit,初始化列表⼀、构造函数在类中有⼀种特殊的成员函数,它的名字与类名相同,我们在创建类的时候,这个特殊的成员函数就会被系统调⽤。
这个成员函数,就叫“构造函数”。
因为构造函数会被系统⾃动调动,构造函数的⽬的就是初始化类对象的数据成员。
(1)构造函数没有返回值,这是构造函数的特殊之处。
(2)不可以⼿⼯调⽤构造函数,否则编译会出错。
(3)正常情况下,构造函数应该被声明为public,因为创建⼀个对象时,系统要替我们调⽤构造函数,这说明构造函数是⼀个public的成员类缺省的成员是私有成员,因此对于构造函数我们必须将其声明为publicclass Time{private:int Millsecond; // 毫秒public:int Hour; // ⼩时int Minute; // 分钟int Second; // 秒钟void initTime(int tmpHour, int tmpMinute ,int tmpSecond){Hour = tmpHour;Minute = tmpMinute;Second = tmpSecond;}void initMillTime(int mls){Millsecond = mls; // 成员函数可以访问成员变量,不管成员是否私有}public:// 构造函数Time(int tmpHour, int tmpMinute ,int tmpSecond = 12){Hour = tmpHour;Minute = tmpMinute;Second = tmpSecond;initMillTime(0);cout << “调⽤了构造函数” <<endl;}Time() // 不加参数的构造函数{Hour = 0;Minute = 0;Second = 0;initMillTime(0);cout <<”不加参数的构造函数” <<endl;}// 单参数构造函数Time(int tmpHour){Hour = tmpHour;Minute = 59;Second = 59;initMillTime(0);cout << “调⽤了构造函数Time(int tmpHour)” <<endl;}}Time MyTime = Time(12,13,52); // 创建类对象Time MyTime1(12,13,52); // 创建类对象⼆、多个构造函数⼀个类中可以有多种构造函数,就可以为类对象的创建提供多种初始化⽅法,但是多个构造函数需要有点不同的地⽅,⽐如参数数量或者参数类型。
c语言结构体的构造函数C语言结构体的构造函数1. 引言C语言是一种通用的高级编程语言,广泛应用于嵌入式系统开发、操作系统以及各种应用程序的开发中。
其中,结构体是C语言中一种非常重要的数据类型,用于组织和管理不同类型的数据。
结构体的构造函数是一种用来初始化结构体对象的特殊函数,它能够为结构体成员赋予初始值,提高代码的可读性和可维护性。
2. 结构体及其定义结构体是一种用户自定义的数据类型,它可以由不同类型的数据组成,这些数据称为结构体的成员。
在C语言中,结构体的定义通常包含在函数外部,以便在整个程序中都能访问到该结构体。
下面是一个简单的结构体定义的示例:```cstruct Student {char name[20];int age;float score;};```上述代码定义了一个名为`Student`的结构体,它包含了三个成员变量,分别是名字、年龄和分数。
3. 构造函数的定义结构体的构造函数是一种特殊的函数,它会在创建结构体对象时被调用,用来为结构体成员赋予初始值。
构造函数的命名通常与结构体的名称相同,并在名称前加上一个下划线。
下面是一个构造函数的定义示例:```cvoid Student_init(struct Student* stu, char* name, int age, float score) {strcpy(stu->name, name);stu->age = age;stu->score = score;}```上述代码定义了一个名为`Student_init`的构造函数,它接受一个指向结构体对象的指针`stu`,以及三个用于初始化结构体成员的参数。
在构造函数内部,通过使用`strcpy`函数来复制字符串,将传入的`name`参数赋值给结构体的`name`成员变量;然后直接将`age`和`score`参数赋值给结构体的相应成员变量。
4. 构造函数的使用使用结构体的构造函数可以方便地创建并初始化结构体对象。
c++类的构造函数详解一、构造函数是干什么的class Counter{public:// 类Counter的构造函数// 特点:以类名作为函数名,无返回类型Counter(){m_value = 0;}private:// 数据成员int m_value;}该类对象被创建时,编译系统对象分配内存空间,并自动调用该构造函数->由构造函数完成成员的初始化工作eg: Counter c1;编译系统为对象c1的每个数据成员(m_value)分配内存空间,并调用构造函数Counter( )自动地初始化对象c1的m_value值设置为0故:构造函数的作用:初始化对象的数据成员。
二、构造函数的种类class Complex{private :double m_real;double m_imag;public:// 无参数构造函数// 如果创建一个类你没有写任何构造函数,则系统会自动生成默认的无参构造函数,函数为空,什么都不做// 只要你写了一个下面的某一种构造函数,系统就不会再自动生成这样一个默认的构造函数,如果希望有一个这样的无参构造函数,则需要自己显示地写出来Complex(void){m_real = 0.0;m_imag = 0.0;}// 一般构造函数(也称重载构造函数)// 一般构造函数可以有各种参数形式,一个类可以有多个一般构造函数,前提是参数的个数或者类型不同(基于c++的重载函数原理)// 例如:你还可以写一个Complex( int num)的构造函数出来// 创建对象时根据传入的参数不同调用不同的构造函数Complex(double real, double imag){m_real = real;m_imag = imag;}// 复制构造函数(也称为拷贝构造函数)// 复制构造函数参数为类对象本身的引用,用于根据一个已存在的对象复制出一个新的该类的对象,一般在函数中会将已存在对象的数据成员的值复制一份到新创建的对象中// 若没有显示的写复制构造函数,则系统会默认创建一个复制构造函数,但当类中有指针成员时,由系统默认创建该复制构造函数会存在风险,具体原因请查询有关“浅拷贝” 、“深拷贝”的文章论述Complex(const Complex & c){// 将对象c中的数据成员值复制过来m_real = c.m_real;m_imag = c.m_imag;}// 类型转换构造函数,根据一个指定的类型的对象创建一个本类的对象,//需要注意的一点是,这个其实就是一般的构造函数,但是对于出现这种单参数的构造函数,C++会默认将参数对应的类型转换为该类类型,有时候这种隐私的转换是我们所不想要的,所以需要使用explicit来限制这种转换。
// 例如:下面将根据一个double类型的对象创建了一个Complex对象Complex(double r){m_real = r;m_imag = 0.0;}// 等号运算符重载(也叫赋值构造函数)// 注意,这个类似复制构造函数,将=右边的本类对象的值复制给等号左边的对象,它不属于构造函数,等号左右两边的对象必须已经被创建// 若没有显示的写=运算符重载,则系统也会创建一个默认的=运算符重载,只做一些基本的拷贝工作Complex &operator=( const Complex &rhs ){// 首先检测等号右边的是否就是左边的对象本身,若是本对象本身,则直接返回if ( this == &rhs ){return *this;}// 复制等号右边的成员到左边的对象中this->m_real = rhs.m_real;this->m_imag = rhs.m_imag;// 把等号左边的对象再次传出// 目的是为了支持连等eg: a=b=c 系统首先运行b=c// 然后运行a= ( b=c的返回值,这里应该是复制c值后的b对象)return *this;}};下面使用上面定义的类对象来说明各个构造函数的用法:int main(){// 调用了无参构造函数,数据成员初值被赋为0.0Complex c1,c2;// 调用一般构造函数,数据成员初值被赋为指定值Complex c3(1.0,2.5);// 也可以使用下面的形式Complex c3 = Complex(1.0,2.5);// 把c3的数据成员的值赋值给c1// 由于c1已经事先被创建,故此处不会调用任何构造函数// 只会调用= 号运算符重载函数c1 = c3;// 调用类型转换构造函数// 系统首先调用类型转换构造函数,将5.2创建为一个本类的临时对象,然后调用等号运算符重载,将该临时对象赋值给c1c2 = 5.2;// 调用拷贝构造函数( 有下面两种调用方式)Complex c5(c2);Complex c4 = c2; // 注意和= 运算符重载区分,这里等号左边的对象不是事先已经创建,故需要调用拷贝构造函数,参数为c2//这一点特别重要,这儿是初始化,不是赋值。
其实这儿就涉及了C++中的两种初始化的方式:复制初始化和赋值初始化。
其中c5采用的是复制初始化,而c4采用的是赋值初始化,这两种方式都是要调用拷贝构造函数的。
}三、思考与测验1. 仔细观察复制构造函数Complex(const Complex & c){// 将对象c中的数据成员值复制过来m_real = c.m_real;m_img = c.m_img;}为什么函数中可以直接访问对象c的私有成员?答:(网上)因为拷贝构造函数是放在本身这个类里的,而类中的函数可以访问这个类的对象的所有成员,当然包括私有成员了。
2. 挑战题,了解引用与传值的区别Complex test1(const Complex& c){return c;}Complex test2(const Complex c){return c;}Complex test3(){static Complex c(1.0,5.0);return c;}Complex& test4(){static Complex c(1.0,5.0);return c;}void main(){Complex a,b;// 下面函数执行过程中各会调用几次构造函数,调用的是什么构造函数?test1(a);test2(a);b = test3();b = test4();test2(1.2);// 下面这条语句会出错吗?test1(1.2); //test1( Complex(1.2 )) 呢?}答:为了便于看构造函数的调用效果,我将类重新改一下,添加一些输出信息,代码如下:View Code下面是程序运行结果:第一次运行结果第2次运行结果第3次运行结果四、附录(浅拷贝与深拷贝)上面提到,如果没有自定义复制构造函数,则系统会创建默认的复制构造函数,但系统创建的默认复制构造函数只会执行“浅拷贝”,即将被拷贝对象的数据成员的值一一赋值给新创建的对象,若该类的数据成员中有指针成员,则会使得新的对象的指针所指向的地址与被拷贝对象的指针所指向的地址相同,delete该指针时则会导致两次重复delete而出错。
下面是示例:【浅拷贝与深拷贝】#include <iostream.h>#include <string.h>class Person{public :// 构造函数Person(char * pN){cout << "一般构造函数被调用!\n";m_pName = new char[strlen(pN) + 1];//在堆中开辟一个内存块存放pN所指的字符串if(m_pName != NULL){//如果m_pName不是空指针,则把形参指针pN所指的字符串复制给它strcpy(m_pName ,pN);}}// 系统创建的默认复制构造函数,只做位模式拷贝Person(Person & p){//使两个字符串指针指向同一地址位置m_pName = p.m_pName;}~Person( ){delete m_pName;}private :char * m_pName;};void main( ){Person man("lujun");Person woman(man);// 结果导致man 和 woman 的指针都指向了同一个地址// 函数结束析构时// 同一个地址被delete两次}// 下面自己设计复制构造函数,实现“深拷贝”,即不让指针指向同一地址,而是重新申请一块内存给新的对象的指针数据成员Person(Person & chs);{// 用运算符new为新对象的指针数据成员分配空间m_pName=new char[strlen(p.m_pName)+ 1];if(m_pName){// 复制内容strcpy(m_pName ,chs.m_pName);}// 则新创建的对象的m_pName与原对象chs的m_pName不再指向同一地址了}参考地址:/823160/194307下面讨论一个重要问题是:构造函数的显式调用大家看看下面这段代码的输出结果是什么?这段代码有问题么?#include <iostream>class CTest{public:CTest(){m_a = 1;}CTest(int b){m_b = b;CTest();}~CTest(){}void show{std::cout << m_a << std::endl;std::cout << m_b << std::endl;}private:int m_a;int m_b;};void main(){CTest myTest(2);myTest.show();}-----------------------------------------------------------【分析】-----------------------------------------------------------输出结果中,m_a是一个不确定的值,因为没有被赋初值,m_b 为2注意下面这段代码CTest(int b){m_b = b;CTest();}在调用CTest()函数时,实际上是创建了一个匿名的临时CTest类对象,CTest()中赋值m_a = 1 也是对该匿名对象赋值,故我们定义的myTest的m_a其实没有被赋值。
说白了,其实构造函数并不像普通函数那样进行一段处理,而是创建了一个对象,并且对该对象赋初值,所以显式调用构造函数无法实现给私有成员赋值的目的。