<C++ - 拷贝构造> 2018-01-12
01、拷贝构造:
#include <iostream> using namespace std; /* 回顾上节的内容: 1.构造和析构 2.new delete 3.delete[] 新的知识 (拷贝的关键字: memcpy) 1.拷贝构造 ->构造函数 函数名和类名相同 没有返回值 定义: 用拷贝的方式构造对象 调用拷贝构造 参数为 该类对象的构造函数 关于引用: 1.拷贝构造 参数必须为引用 2.加引用的好处 节约内存 效率比指针高 构造和析构 调用时候 对象出生和死亡 引用直接用别名方式 (没有出生新的对象) 拷贝如果是直接赋值(指针 申请了堆内存的话 两个对象的指针指向同一块堆内存)释放一个对象的内存 另外一个对象 指针就无效了 **深拷贝 每个对象单独申请内存(一个一口锅)-->看拷贝中有没有单独申请内存 浅拷贝 直接赋值(两个人共同背锅) 注意 : 拷贝构造: 问题1: 引用 问题2: 深拷贝 */ //========================================类函数====================================== class A { private: char *arr; // 指针 它申请一块堆内存 int x; // x内存大小 x个char public: A() // 参构造函数 没有返回值 自动调用 { cout << "调用无参构造函数" << endl; this->arr = NULL; // 给对象中的arr赋值 this->x = 0; } A(int x) { cout << "调用有参构造函数" << endl; this->arr = new char[x]; // 申请内存 this->x = x; } A(A & other) // 拷贝构造 { /** 参数是同类型的对象 other形参 -->相当是 sum shis指向当前对象相当于 (23)的fnu other拷贝的是sum --> 调用拷贝构造函数 所以必须加引用 拷贝 -->内容拷贝 直接用参数 定义一个新的形参 引用 取别名 不全定义新的形参 */ cout << "拷贝构造函数" << endl; this->arr = new char[other.x]; memcpy(this->arr, other.arr, other.x); // 内存拷贝函数 //头文件: memcry.h this->x = other.x; } ~A() // 析构函数 --> 没有返回值 没有参数 自动调用 { cout << "调用析构函数" << endl; if (arr != NULL) { delete[]arr; // 释放内存 arr = NULL; } } // 判断两个人能否结婚 void married(A other1, A other2) // married 通过对象调用 那个对象调用 this指向哪个对象 { // 通过对象调用 -> this指针指向的对象 this->x; other1.x; other2.x; } void mamied(A other) { cout << "是否婚配" << endl; } }; /** new delete 申请对象的内存空间的时候 调用对象的构造/析构函数 delete[] 调用每个对象的析构函数 */ //==========================================新内容==================================== int main() { #if 0 { A sum; // 定义一个对象sum 在栈区 (调用无参构造) A fnu(sum); // 调用拷贝构造 (23) /** sum.arr 指向一个内存空间 fnu.arr = sum.arr fnu.arr和sum.arr指向同一块内存空间 看拷贝之后的结果 拷贝之后两个指针指向同一块内存 浅拷贝 指向不同的空间 深拷贝 */ sum.mamied(fnu); // 函数 传参 实参 -->形参赋值 形参拷贝实参 } #endif A danny, logs, st; danny.married(logs, st); getchar(); return 0; }
02、static和const:
#include <iostream> using namespace std; /* static 静态 1.修饰普通变量 内存在静态存储区(内存四区 堆区 栈区 全局静态常量区 代码区) 只会开辟一次内存 函数结束不释放内存 2.修饰全局变量 限制作用域 -> 变量只能在当前文件使用(对针extern) extern :在这个文件中使用其他文件中的变量 3.修饰类的成员变量(C++) 3.1 静态成员变量 不能在构造函数中赋值 必须在类外赋值 -> 用类名访问 3.2 静态成员不专属于某个对象 属于这个类 所有对象公用同一个静态成员 静态成员函数 不能修改非静态成员(没有this指针) const 修饰常量 const int 只能定义的时候赋值 定义之后不能修改值 修饰指针 const int*: 常量指针 / int *const: 指针常量 const int*p *p 不可以改 --> 指向的内容不可以改 int *const p p 不能改 --> 不能改指针的指向 const A&temp 和 A&const temp 修饰 &temp -> 不能改引用的内容 修饰的temp 引用 不能变成其他对象的引用(本身也不能变成其他对象的引用 所以加或者不加 没区别) 1.const 修饰成员变量 常属性成员变量 常量 -> 赋值之后不能修改 2.初始化形参列表 格式 const 成员变量 只能通过初始化成员 列表赋值 后面也不能修改它的值 3.其他const用法: 3.1. 修饰参数 不能修改参数的值 一般对象 传参使用引用 为了避免在参数中修改了这个实参的值 加上const const 修改形参 限定形参的使用 不限定实参 3.2. 修饰返回值 放函数前面(不用) 3.3 修饰成员函数 常属性成员函数 放在函数后面 常属性成员函数 :1.不能修改成员变量的值 2.不能调用非常属性成员函数 */ class people { private: int age; char name[30]; static int earth; // 静态成员 public: /* 构造函数和析构函数没有返回值 */ people() { cout << "调用无参构造函数" << endl; age = 0; strcpy(name, "baby"); // 拷贝 //earth = 0; } void eat() { this->age; this->earth++; } void print() { cout << earth << endl; } static void play() // 静态成员函数 --> 不能使用this指针 { //age++; //this->age++; earth++; } }; int people::earth = 100; int fun() { static int x = 1; x++; return x; } class human { private: const int x; int y; public: /*human() // 无参构造 { //x = 0; // 构造中不能直接给这个常属性成员赋值 y = 0; }*/ // 初始化成员列表 // 格式: 构造函数名(参数):成员名1(参数1),成员名2(参数2)....// 用括号里面的参数给成员赋值 human() :x(0), y(0) { cout << "调用无参构造" << endl; y = 3; // 赋值顺序 先成员列表 后函数体 } human(int x, int y) :x(x) { cout << "调用有参构造" << endl; this->y = y; } void print() const { cout << x << '\t' << y << endl; } void married(const human&other) // 没有限定实参 { //other.y = 100; // 错误修改了实参的值 print(); } void play() const // 常属性成员函数 :1.不能修改成员变量的值 2.不能调用非常属性成员函数 { } }; int main() { #if 0 /* cout << fun() << endl; cout << fun() << endl; cout << fun() << endl; */ people memore; // 定义一个对象 memore.eat(); memore.eat(); memore.print(); memore.eat(); memore.print(); memore.play(); #endif human bug; human fum(3, 5); bug.print(); fum.print(); bug.married(fum); fum.print(); getchar(); return 0; } /* strcpy(拷贝函数) --> const 作业: 1. 写一个 mystring类(用指针申请堆内存 存放一个字符串) 需要写拷贝构造 2. 给类中const成员和static成员初始化 */