一,类的概念及封装
1.什么是封装
2.类的访问控制
在C++中可以对类的属性和方法定义访问级别,public修饰的属性和方法,可以在类的内部访问,也可以在类的外部进行访问。private修饰的属性和方法,只能在类的内部进行访问。
3.类的意义
4,圆类的抽象和封装
# include<iostream> using namespace std; /* 抽象一个圆类,并对圆的属性和方法进行封装 */ class Circle { private: double r; /* 圆类的半径属性 */ public: void setR(double r) /* 设置圆的半径 */ { this->r = r; } double getR() /* 获取圆的半径 */ { return this->r; } };
二,构造函数
1.前言
当我们创建一个对象的时候,常常需要做某些初始化操作,例如属性进行赋初值。为了解决这个问题,C++编译器提供了构造函数来处理对象的初始化。构造函数是一种特殊的成员函数,与其他成员函数不同,不需要用户来调用它,而是在创建对象时自动执行。
2.构造函数的定义及调用方式
3.构造函数的分类
4.无参构造函数示例及调用
# include<iostream> using namespace std; /* 抽象一个圆类,并对圆的属性和方法进行封装 */ class Circle { private: double r; /* 圆类的半径属性 */ public: Circle() /* 无参构造函数 */ { cout << "无参构造函数被执行" << endl; } void setR(double r) /* 设置圆的半径 */ { this->r = r; } double getR() /* 获取圆的半径 */ { return this->r; } }; int main() { /* 无参构造函数的调用方式 */ Circle circle1,circle2; }
5.有参构造函数示例及调用
# include<iostream> using namespace std; /* 抽象一个圆类,并对圆的属性和方法进行封装 */ class Circle { private: double r; /* 圆类的半径属性 */ public: Circle(int a,int b) /* 有参构造函数 */ { cout << "有参构造函数被调用" << endl; } void setR(double r) /* 设置圆的半径 */ { this->r = r; } double getR() /* 获取圆的半径 */ { return this->r; } }; int main() { /* 有参构造函数调用方式一 */ Circle circle1(1, 2); /* 有参构造函数调用方式二:程序员手工直接调用构造方法 */ Circle circle2 = Circle(1, 2); }
6.拷贝构造函数示例及调用
1.拷贝构造函数的调用方式
2.拷贝构造函数调用方式示例
# include<iostream> using namespace std; class Location { private: int x; int y; public: Location() { cout << "无参构造函数被执行" << endl; } Location(int x,int y) { this->x = x; this->y = y; cout << "有参构造函数被执行" << endl; } Location(const Location& location) { this->x = location.x; this->y = location.y; cout << "拷贝构造函数被执行" << endl; } ~Location() { cout << "x = " << this->x << ",y = " << this->y << "析构函数被执行" << endl; } }; /* 模拟拷贝构造函数调用方式三 */ void setLocation(Location location) { cout << "setLocation()全局函数..." << endl; } /* 模拟拷贝构造函数调用方式四 */ Location getLocation() { cout << "getLocation()全局函数..." << endl; Location location(100, 200); return location; } /* 研究拷贝构造函数的调用 */ int main() { /* 拷贝构造函数调用方式一 */ cout << "###############方式一###############" << endl; Location loc1(1, 2); Location loc2 = loc1; /* 拷贝构造函数调用方式二 */ cout << "###############方式二###############" << endl; Location loc3(10, 20); Location loc4(loc3); /* 拷贝构造函数调用方式三 */ cout << "###############方式三###############" << endl; Location loc5(5, 10); setLocation(loc5); /* 拷贝构造函数调用方式四 */ cout << "###############方式四###############" << endl; /* getLocation()产生匿名对象赋值给loc6后,匿名对象执行析构函数,然后对象销毁 */ Location loc6; loc6 = getLocation(); /* getLocation()产生匿名对象赋值给loc7,匿名对象被扶正,直接转成新对象 */ Location loc7 = getLocation(); }
7.构造函数小结
三,析构函数
1.析构函数的定义及调用方式
2.析构函数的使用
析构通常是在对象生命周期结束之前调用,我们会在此时去释放我们在对象中创建的堆内存,保证程序的合理性。
# define _CRT_SECURE_NO_WARNINGS # include<iostream> using namespace std; class Student { private: char * name; int age; public: Student(char * name, int age) { /* 在构造函数中分配堆内存 */ this->name = (char *)malloc(sizeof(name)+1); /* 初始化成员变量 */ strcpy(this->name, name); this->age = age; cout << "构造函数被执行..." << endl; } ~Student() { if (this->name != NULL) { /* 在析构函数中释放堆内存 */ free(this->name); this->name = NULL; this->age = 0; } cout << "析构函数被执行..." << endl; } void print() { cout << this->name << " = " << this->age << endl; } }; int main() { Student stu("王刚", 21); stu.print(); return 0; }
四,多个对象的构造函数和析构函数
1.对象初始化列表
当我们有一个类成员,它本身是一个类,而且这个成员只有一个带参数的构造函数,没有默认构造函数,这个时候要对这个类成员进行初始化,就必须调用这个类成员的带参构造函数,这个时候可以在定义成员的时候采用该构造函数初始化对象,但是我们想要动态的初始化,则需要将该成员动态接受外界数据,因此出现了对象初始化列表这个概念。
2.类中成员为const修饰
当我们有个类成员,它被const修饰,那么在初始化的时候可以直接在定义变量的时候初始化,也可以在使用对象初始化列表的时候进行初始化。
3.对象初始化示例
# include<iostream> using namespace std; /* 定义A类 */ class A { private: int a; int b; public: A(int a, int b) { this->a = a; this->b = b; cout << "A(" << this->a << "," << this->b << ")有参构造函数被执行" << endl; } ~A() { cout << "~A(" << this->a << ", " << this->b << ")析构函数被执行" << endl; } }; /* 定义类B */ class B { private: A a1; A a2; const int n; const int m = 10; public: /* 对象初始化列表:让成员变量从外界接收的方式来初始化 */ B(int x,int y):a1(x,y),a2(10,20),n(100) { cout << "B(int x,int y)有参构造函数被执行" << endl; } ~B() { cout << "~B()析构函数被执行" << endl; } }; int main() { B b(1, 2); return 0; }
4.构造函数和析构函数的执行顺序
五,拷贝构造函数的深拷贝和浅拷贝
1.拷贝构造函数的执行原理
拷贝构造函数有四种调用方式,当我们不写拷贝构造函数的时候,C++默认的帮我们写了拷贝构造函数,其函数体实现的是简单的成员变量的值的拷贝。这种默认的拷贝方式,我们称为浅拷贝,即只是简单的复制成员变量的值到另一个对象中。
2.深拷贝问题的抛出
当我们的成员变量是动态分配的一组堆内存的时候,这个时候C++默认的为我们写的拷贝构造函数把成员变量的值进行了复制,那么副本也会指向原始对象所分配的堆内存,当我们在析构函数中释放堆内存的时候,就会发生两次析构现象(一次是原始对象释放堆内存,一次是副本对象释放堆内存)因此造成程序崩溃。
3.深拷贝代码示例
# define _CRT_SECURE_NO_WARNINGS # include<iostream> using namespace std; class Student { private: char * name; int age; public: /* 无参构造函数 */ Student() { cout << "无参构造函数被执行..." << endl; } /* 有参构造函数 */ Student(char * name, int age) { /* 在构造函数中分配堆内存 */ this->name = (char *)malloc(sizeof(name) + 1); /* 初始化成员变量 */ strcpy(this->name, name); this->age = age; cout << "有参构造函数被执行..." << endl; } /* 拷贝构造函数 */ Student(const Student &student) { /* 重新分配内存 */ this->name = (char *)malloc(sizeof(student.name) + 1); /* 初始化成员变量 */ strcpy(this->name, name); this->age = age; cout << "拷贝构造函数被执行..." << endl; } /* 析构函数 */ ~Student() { if (this->name != NULL) { free(this->name); this->name = NULL; this->age = 0; } cout << "析构函数被执行..." << endl; } void print() { cout << this->name << " = " << this->age << endl; } }; int main() { Student stu1("王刚", 22); /* 此时拷贝构造函数执行,在创建副本的时候进行深拷贝,则不会出现析构问题 */ Student stu2 = stu1; return 0; }
原文:http://www.cnblogs.com/metalsteel/p/6266505.html