第02课 复制构造函数与对象成员
- 格式:rtf
- 大小:49.56 KB
- 文档页数:4
详解C++中构造函数,拷贝构造函数和赋值函数的区别和实现C++中⼀般创建对象,拷贝或赋值的⽅式有构造函数,拷贝构造函数,赋值函数这三种⽅法。
下⾯就详细⽐较下三者之间的区别以及它们的具体实现1.构造函数构造函数是⼀种特殊的类成员函数,是当创建⼀个类的对象时,它被调⽤来对类的数据成员进⾏初始化和分配内存。
(构造函数的命名必须和类名完全相同)⾸先说⼀下⼀个C++的空类,编译器会加⼊哪些默认的成员函数默认构造函数和拷贝构造函数析构函数赋值函数(赋值运算符)取值函数**即使程序没定义任何成员,编译器也会插⼊以上的函数!注意:构造函数可以被重载,可以多个,可以带参数;析构函数只有⼀个,不能被重载,不带参数⽽默认构造函数没有参数,它什么也不做。
当没有重载⽆参构造函数时,A a就是通过默认构造函数来创建⼀个对象下⾯代码为构造函数重载的实现<span style="font-size:14px;">class A{int m_i;Public:A(){Cout<<”⽆参构造函数”<<endl;}A(int i):m_i(i) {} //初始化列表}</span>2.拷贝构造函数拷贝构造函数是C++独有的,它是⼀种特殊的构造函数,⽤基于同⼀类的⼀个对象构造和初始化另⼀个对象。
当没有重载拷贝构造函数时,通过默认拷贝构造函数来创建⼀个对象A a;A b(a);A b=a; 都是拷贝构造函数来创建对象b强调:这⾥b对象是不存在的,是⽤a 对象来构造和初始化b的!!先说下什么时候拷贝构造函数会被调⽤:在C++中,3种对象需要复制,此时拷贝构造函数会被调⽤1. 1)⼀个对象以值传递的⽅式传⼊函数体2. 2)⼀个对象以值传递的⽅式从函数返回3. 3)⼀个对象需要通过另⼀个对象进⾏初始化什么时候编译器会⽣成默认的拷贝构造函数:1. 1)如果⽤户没有⾃定义拷贝构造函数,并且在代码中使⽤到了拷贝构造函数,编译器就会⽣成默认的拷贝构造函数。
拷贝构造函数的用法-电脑资料jiu_acm纸上得来终觉浅绝知此事要躬行拷贝构造函数的用法1.拷贝构造函数是与类名相同,其形参是本类的对象的引用,。
2.拷贝构造函数会在以下三种情况下被调用:1).当用类的一个对象去初始化该类的另一个对象时。
2).如果函数的形参是类的对象,调用该函数,将对象作为函数实参传递给函数的形参时。
3).如果函数的返回值是类的对象,函数执行完成,将返回值返回时。
3.浅拷贝的失败例子:1 #include2 #include34 using namespace std;567 class str8 {9 private:10 char *s;11 int len;12 public:13 str()14 {15 len=0;16 s=NULL;17 }18 str(const char *p)19 {20 len=strlen(p);21 s=new char[len+1];22 strcpy(s,p);23 }24 ~str()25 {26 if(s!=NULL)27 {28 delete []s;29 s=NULL;30 }31 }32 };3334 int main()35 {36 str s1("I love you!");37 str s2=s1; //这里会发生错误,电脑资料《拷贝构造函数的用法》(https://www.)。
38 return 0;39 }之所以发生错误是因为两个对象在析构时都要delete那块堆里的内存,但是程序里是浅拷贝,也就是说,s2只拷贝了s1的堆内存的地址,s2的s指针指向s1申请的堆内存,两次delete同一块内存,明显不合法。
故而需要增加自定义拷贝构造函数,即深拷贝。
见于下例:1 str(str &r)2 {3 len=r.len;4 if(len!=0)5 {6 s=new char[len+1];7 strcpy(s,r.s);8 }9 }4.注意:1).在自定义拷贝构造函数后,缺省拷贝构造函数和构造函数失效,构造函数需要自定义。
c++ 复制构造函数拷贝构造函数C++中的复制构造函数,也称为拷贝构造函数,是一种特殊的构造函数,它的作用是用一个已经存在的对象去初始化一个新的对象。
当我们没有定义复制构造函数时,C++会自动生成一个默认的复制构造函数,它的实现方法是将一个对象的每个成员变量的值都复制到新对象中。
但是,当对象中存在指针类型的成员变量时,简单的值复制可能会导致内存泄漏等问题。
因此,我们需要手动实现复制构造函数,以确保正确地复制对象。
复制构造函数的定义格式如下:ClassName(const ClassName &obj)其中,ClassName是类名,obj是待复制的对象。
在复制构造函数中,一般需要做以下几个步骤:1. 判断待复制对象和新对象是否是同一个对象,如果是,则不需要复制。
2. 分配内存空间,对新对象进行初始化。
3. 将待复制对象的成员变量值复制到新对象中。
如果存在指针类型的成员变量,则需要进行深拷贝,即重新分配内存空间并将指针指向的值复制到新内存中。
4. 返回新对象。
下面是一个示例代码:```class Person {public:Person() {name = new char[20];age = 0;}Person(const Person &obj) { if (&obj == this) {return;}name = new char[20];strcpy(name, );age = obj.age;}~Person() {delete[] name;}private:char *name;int age;};```在上面的代码中,我们定义了一个包含指针类型成员变量的类Person,并手动实现了复制构造函数。
在复制构造函数中,我们首先判断待复制对象和新对象是否是同一个对象,如果是,则不需要进行复制。
然后,我们重新分配内存空间,将待复制对象的成员变量值复制到新对象中,并对指针类型成员变量进行了深拷贝。
C++拷贝(复制)构造函数详解⼀. 什么是拷贝构造函数⾸先对于普通类型的对象来说,它们之间的复制是很简单的,例如:[c-sharp]1. int a = 100;2. int b = a;⽽类对象与普通对象不同,类对象内部结构⼀般较为复杂,存在各种成员变量。
下⾯看⼀个类对象拷贝的简单例⼦。
[c-sharp]1. #include <iostream>2. using namespace std;3.4. class CExample {5. private:6. int a;7. public:8. //构造函数9. CExample(int b)10. { a = b;}11.12. //⼀般函数13. void Show ()14. {15. cout<<a<<endl;16. }17. };18.19. int main()20. {21. CExample A(100);22. CExample B = A; //注意这⾥的对象初始化要调⽤拷贝构造函数,⽽⾮赋值23. B.Show ();24. return 0;25. }运⾏程序,屏幕输出100。
从以上代码的运⾏结果可以看出,系统为对象 B 分配了内存并完成了与对象 A 的复制过程。
就类对象⽽⾔,相同类型的类对象是通过拷贝构造函数来完成整个复制过程的。
下⾯举例说明拷贝构造函数的⼯作过程。
[c-sharp]1. #include <iostream>2. using namespace std;3.4. class CExample {5. private:6. int a;7. public:8. //构造函数9. CExample(int b)10. { a = b;}11.12. //拷贝构造函数13. CExample(const CExample& C)14. {15. a = C.a;16. }17.18. //⼀般函数19. void Show ()20. {21. cout<<a<<endl;22. }23. };24.25. int main()26. {27. CExample A(100);28. CExample B = A; // CExample B(A); 也是⼀样的29. B.Show ();30. return 0;31. }CExample(const CExample& C) 就是我们⾃定义的拷贝构造函数。
c++ 构造函数复制构造函数C++构造函数和复制构造函数是面向对象编程中重要的概念。
构造函数是在创建对象时自动调用的函数,用于初始化对象的成员变量。
复制构造函数则是在对象复制时自动调用的函数,用于将一个对象的值复制到另一个对象中。
本文将介绍 C++ 构造函数和复制构造函数的概念、用法和注意事项。
1. 构造函数构造函数是一种特殊的成员函数,用于初始化对象的成员变量。
构造函数的名称必须与类名相同,没有返回值,也不需要显式调用。
当创建对象时,系统会自动调用该类的构造函数进行对象的初始化。
例如:```class MyClass {public:MyClass() {// 构造函数代码}};```在上面的示例中,定义了一个名为 MyClass 的类,该类包含一个构造函数。
当创建 MyClass 对象时,该构造函数将被自动调用进行对象的初始化。
在 C++ 中,构造函数可以有多个重载版本。
例如,可以定义一个带参数的构造函数:```class MyClass {public:MyClass(int value) {// 构造函数代码}};```在上面的示例中,定义了一个带一个整型参数的 MyClass 构造函数。
当使用 MyClass(int value) 创建对象时,该构造函数将被自动调用进行对象的初始化。
2. 复制构造函数复制构造函数是一种特殊的构造函数,用于将一个对象的值复制到另一个对象中。
当使用一个对象创建另一个对象时,系统会自动调用该类的复制构造函数进行对象的复制。
例如:```class MyClass {public:MyClass(const MyClass& other) {// 复制构造函数代码}};```在上面的示例中,定义了一个名为 MyClass 的类,该类包含一个复制构造函数。
当使用一个 MyClass 对象创建另一个 MyClass 对象时,该复制构造函数将被自动调用进行对象的复制。
c++ 复制构造函数拷贝构造函数C++复制构造函数,也被称为拷贝构造函数,在对象被复制时被调用。
它用于将一个对象的值传递给另一个对象,以便它们具有相同的值,但是在不同的内存位置。
复制构造函数是由编译器自动生成的,但是也可以手动编写。
如果没有手动编写复制构造函数,C++编译器会自动生成一个默认的复制构造函数,该函数执行逐个复制对象的每个成员变量。
但是,如果类中有指针、动态内存分配或其他资源,可能需要手动编写复制构造函数。
否则,在复制对象时,新对象和旧对象将共享指针和资源,从而导致不可预测的结果。
使用以下格式定义复制构造函数:类名(const 类名& 对象名){// 复制构造函数的代码}其中,const类名&对象名表示传递的参数是一个常量引用,因为不会对该对象进行修改。
使用复制构造函数的示例:#include<iostream>using namespace std;class Person{public:int age;string name;//构造函数Person(int a, string n){age=a;name=n;}//复制构造函数Person(const Person &p){age=p.age;name=;}};int main(){//创建对象p1Person p1(20,'Tom');//将p1的值复制给p2Person p2=p1;//输出p2的值cout<<p2.age<<' '<<<<endl;return 0;}上述示例中,当p1的值复制给p2时,复制构造函数被调用,将p1的值复制到p2中。
最后,输出p2的值,以验证复制构造函数的正确性。
总之,复制构造函数是C++中一个重要的概念,用于在对象被复制时保持对象的数据完整性和相对独立性。
复制构造函数使用复制构造函数是C++中的一种特殊构造函数,它用来创建一个新对象,该对象与原对象具有相同的数据成员值。
在C++中,使用复制构造函数可以有效地复制一个对象的内容,而不需要逐个复制每个数据成员。
在本文中,我们将详细介绍复制构造函数的使用,并提供一些示例来说明其在实际应用中的作用。
```cppClassName(const ClassName &obj);```其中,ClassName是类的名称,obj是一个常量引用参数,用于传递原对象的值。
下面是一个使用复制构造函数的示例:```cpp#include <iostream>using namespace std;class MyClassprivate:int x;public:MyClass( { x = 0; } // 默认构造函数MyClass(const MyClass &obj) { x = obj.x; } // 复制构造函数int getX( { return x; }};int maiMyClass obj1; // 使用默认构造函数创建对象MyClass obj2(obj1); // 使用复制构造函数创建对象cout << "obj1.x = " << obj1.getX( << endl;cout << "obj2.x = " << obj2.getX( << endl;return 0;```在上面的示例中,我们首先定义了一个名为MyClass的类,其中包含一个私有数据成员x和两个公有成员函数(默认构造函数和复制构造函数)。
默认构造函数用于初始化x的值为0,而复制构造函数通过引用另一个MyClass对象来实现x的值的复制。
在main函数中,我们首先使用默认构造函数创建一个名为obj1的对象,然后使用复制构造函数将其值复制给obj2、最后,我们使用getX函数来获取obj1和obj2的x值,并输出结果。
C++类构造函数、拷贝构造函数、复制构造函数、复制构造函数、构造函数显⽰调⽤和隐式调⽤⼀、构造函数是⼲什么的1.class Counter2.{3.public:4.// 类Counter的构造函数5.// 特点:以类名作为函数名,⽆返回类型6.Counter()7.{8.m_value = 0;9.}10.private:11.// 数据成员12.int m_value;13.}该类对象被创建时,编译系统对象分配内存空间,并⾃动调⽤该构造函数->由构造函数完成成员的初始化⼯作eg: Counter c1;编译系统为对象c1的每个数据成员(m_value)分配内存空间,并调⽤构造函数Counter( )⾃动地初始化对象c1的m_value值设置为0故:构造函数的作⽤:初始化对象的数据成员。
⼆、构造函数的种类1.class Complex2.{3.private :4.double m_real;5.double m_imag;6.public:7.Complex() //⼀般构造函数8.{9.m_real = 0.0;10.m_imag = 0.0;11.}12.13.Complex(double real, double imag) //⼀般构造函数14.{15.m_real = real;16.m_imag = imag;17.}18.19.Complex(const Complex & c) //拷贝构造函数20.{21.// 将对象c中的数据成员值复制过来22.m_real = c.m_real;23.m_imag = c.m_imag;24.}25.Complex &operator=( const Complex &rhs ) //赋值构造函数26.{27.// ⾸先检测等号右边的是否就是左边的对象本⾝,若是本对象本⾝,则直接返回28.if ( this == &rhs )29.{30.return *this;31.}32.// 复制等号右边的成员到左边的对象中33.this->m_real = rhs.m_real;34.this->m_imag = rhs.m_imag;35.// 把等号左边的对象再次传出36.return *this;37.}38.};// ⽆参数构造函数// 如果创建⼀个类你没有写任何构造函数,则系统会⾃动⽣成默认的⽆参构造函数,函数为空,什么都不做// 只要你写了⼀个下⾯的某⼀种构造函数,系统就不会再⾃动⽣成这样⼀个默认的构造函数,如果希望有⼀个这样的⽆参构造函数,则需要⾃⼰显⽰地写出来// ⼀般构造函数(也称重载构造函数)// ⼀般构造函数可以有各种参数形式,⼀个类可以有多个⼀般构造函数,前提是参数的个数或者类型不同(基于c++的重载函数原理) // 例如:你还可以写⼀个 Complex( int num)的构造函数出来// 创建对象时根据传⼊的参数不同调⽤不同的构造函数// 复制构造函数(也称为拷贝构造函数)// 复制构造函数参数为类对象本⾝的引⽤,⽤于根据⼀个已存在的对象复制出⼀个新的该类的对象,⼀般在函数中会将已存在对象的数据成员的值复制⼀份到新创建的对象中// 若没有显⽰的写复制构造函数,则系统会默认创建⼀个复制构造函数,但当类中有指针成员时,由系统默认创建该复制构造函数会存在风险,具体原因请查询有关 “浅拷贝” 、“深拷贝”的⽂章论述// 类型转换构造函数,根据⼀个指定的类型的对象创建⼀个本类的对象,//需要注意的⼀点是,这个其实就是⼀般的构造函数,但是对于出现这种单参数的构造函数,C++会默认将参数对应的类型转换为该类类型,有时候这种隐私的转换是我们所不想要的,所以需要使⽤explicit来限制这种转换。
拷贝构造函数用法拷贝构造函数用法拷贝构造函数是一种特殊的构造函数,用于将一个对象的数据成员的值复制到另一个对象中。
拷贝构造函数通常在以下几种情况下被使用:1.对象的初始化当一个新对象被另一个同类型的已存在对象进行初始化时,拷贝构造函数会被调用。
这种情况通常发生在以下几种情况下:•使用一个对象来初始化另一个对象:class MyClass {public:MyClass(int value) : data(value) {}MyClass(const MyClass& other) : data() {}private:int data;};MyClass obj1(10);MyClass obj2(obj1); // 调用拷贝构造函数,将obj1的值复制给obj22.传递对象作为函数参数当一个对象作为参数传递给一个函数时,拷贝构造函数会被调用,以创建函数内的副本。
这样做的好处是,可以避免传递对象的引用导致的数据修改问题。
以下是一个示例:class Person {public:Person(const std::string& name) : name(name) {} // 拷贝构造函数Person(const Person& other) : name() {}private:std::string name;};void printPerson(Person p) {std::cout << "Name: " << () << std::endl;}Person p("John");printPerson(p); // 调用拷贝构造函数,将p复制给函数内的p对象3.返回对象作为函数返回值当一个函数返回一个对象时,拷贝构造函数会被调用,以创建返回值的副本。
以下是一个示例:class Vector {public:Vector(int size) : size(size), values(new int[size]) {}// 拷贝构造函数Vector(const Vector& other) : size(), values(new int []) {for(int i = 0; i < size; i++) {values[i] = [i];}}private:int size;int* values;};Vector createVector(int size) {return Vector(size); // 调用拷贝构造函数,将临时对象返回}Vector v = createVector(5); // 调用拷贝构造函数,将返回值复制给v以上是拷贝构造函数的一些常见用法。
第02课复制构造函数与对象成员
教学目标:掌握复制构造函数的定义,比较它与其它构造函数的异同,掌握含有对象成员的类的构造函数的定义
一、变量的初始化
int x=25;
int y=x;
char z=’w’;
问题:既然可以用常数或有值的变量来初始化一个变量,那么是否可以用对象来初始化另一个对象呢?
二、复制构造函数的定义
●复制构造函数是特殊的构造函数;
●函数只有一个参数,且是其所在类的对象的引用;
●复制构造的原型为:
X::X(const X&);
说明:X为复制构造函数所在类的类名。
例1在类Person中增加一个复制构造函数。
Person :: Person(const Person &m)
{ strcpy(name , );
age = m.age;
sex = m.sex;
}
三、复制构造函数的调用
●声明并初始化对象变量时;
●对象作为函数参数时;
●对象作为函数值被返回时。
说明:若没有为类显式定义复制构造函数,C++编译器将为该类自动生成一个形如X::X(const X &)的缺省构造函数。
例2使用缺省复制构造函数的例子。
定义String类,要求:
1、数据成员为字符串;
2、函数成员为构造函数、析构函数、输出字符串函数。
请编制一个函数来测试类。
// Prog3.cpp
#include <string.h>
#include <iostream.h>
class String
{ private:
char *str;
public:
String(char *s)
{ str = new char[strlen(s)+1];
strcpy(str,s);
}
~String()
{ delete str;
}
void print()
{ cout << str << endl;
}
};
void main(void)
{ String s1="YanShan University welcomes you !";
String s2=s1;
s1.print();
s2.print();
}
说明:s1与s2指向同一个地址,当撤销一个串时,另一个串将没有指向,这在指针运用中是绝对不允许的。
因此,为了避免一些错误,程序员需要自己定义复制构造函数。
复制构造函数:
String(String &s)
{ str=new char[strlen(s.str)+1];
strcpy(str,s.str);
}
// Prog4.cpp
#include <string.h>
#include <iostream.h>
class String
{ private:
char *str;
public:
String(char *s)
{ str = new char[strlen(s)+1];
strcpy(str,s);
}
String(String &s)
{ str=new char[strlen(s.str)+1];
strcpy(str,s.str);
}
~String()
{ delete str;
}
void print()
{ cout << str << endl;
}
};
void main()
{ String s1="YanShan University welcomes you !";
String s2=s1;
s1.print();
s2.print();
}
四、对象成员
在类定义中使用的类类型的数据成员,称为对象成员。
class Person
{ String name;
char sex;
int age;
public:
Person(char *,int,char);
~Person(){};
void print();
};
其中name就是对象成员。
含有对象成员的类X的构造函数的形式为:
X::X(arg1,arg2,…,argn):memb1(arg1),memb2(arg2),…,memb n(argn)
{ … }
例3
Person::Person(char *nm,int ag,char
sx):name(nm),age(ag),sex(sx)
{ … }
例4
Person::Person(char *nm,int ag,char sx):name(nm)
{ age = ag;sex = sx; }
五、程序演示
Prog3.cpp,Prog4.cpp
六、练习
定义一个复数complex类,数据成员有实部和虚部,函数成员有构造函数、复制构造函数、析构函数,按“a+bi”的形式输出一个复数。