1、命名空间
引入命名空间,我们就可以使用命名空间里的函数,以及成员
- 自定义命名空间
namespace daxiaa {
char *name;
int age;
void show() {
cout << "name:" << name << " age:" << age << endl;
}
}
int main() {
using namespace daxiaa;
daxiaa::name = "daxiaa";
daxiaa::age = 100;
daxiaa::show();
name:daxiaa age:100
2、构造函数
1、先在头文件中声明
//构造函数
Student();
Student(int age);
Student(int age, char *name);
2、实现文件中实现
/**
* 无参数构造函数
*/
Student::Student() {
// cout << "no param construct" << endl;
}
/**
* 一个参数的构造函数
* @param age
*/
Student::Student(int age) : Student(age, "daxiaa") {
//cout << "one param construct age = " << age << endl;
this->age = age;
}
/**
* 两个参数构造函数
* @param age
* @param name
*/
Student::Student(int age, char *name) {
// cout << "two param construct age = " << age << " name = " << name << endl;
this->age = age;
this->name = name;
}
3、调用构造函数创建对象
- 普通栈空间创建开辟方式
//调用空参构造函数
Student stu1;
stu1.setAge(100);
stu1.setName("daxiaa");
cout << "age = " << stu1.getAge() << " name = " << stu1.getName() << endl;
Student stu2(100);
- 堆空间创建方式
Student *stu3 = new Student(100, "daxiaa");
if (stu3) {
//手动释放堆空间
delete stu3;
stu3 = NULL;
}
3、析构函数
对象在回收的时候就会首先触发析构函数
Student::~Student() {
cout << "xi gou function"<< endl;
}
4、对象的拷贝
通过以下方式,我们实现了对象的拷贝,我们可以看到打印结果,对象里的属性结果是一样的。但是对象的内存地址不一样。
Student student1(100, "xiaoming");
Student student2 = student1;
cout << " student1.adress " << &student1 << " student1.name: " << student1.getName()
<< " student1.age: " << student1.getAge() << endl;
cout << " student2.adress " << &student2 << " student2.name: " << student2.getName()
<< " student2.age: " << student2.getAge() << endl;
student1.adress 0x70465ff900 student1.name: xiaoming student1.age: 100
student2.adress 0x70465ff8f0 student2.name: xiaoming student2.age: 100
5、 拷贝构造函数
- 自定义拷贝构造函数
上面的例子之所以可以实现赋值操作,是因为默认调用了类中的拷贝构造函数,我们也可以自定义拷贝构造函数
/**
* 自定义拷贝构造函数
* @param student
*/
Student::Student(const Student &student) {
cout << "kao bei gou zhao hanshu" << endl;
this->age = student.age + 100;
this->name = "hello world";
}
Student student1(100, "xiaoming");
Student student2 = student1;
cout << " student1.adress " << &student1 << " student1.name: " << student1.getName()
<< " student1.age: " << student1.getAge() << endl;
cout << " student2.adress " << &student2 << " student2.name: " << student2.getName()
<< " student2.age: " << student2.getAge() << endl;
student1.adress 0x2df19ff620 student1.name: xiaoming student1.age: 100
student2.adress 0x2df19ff610 student2.name: hello world student2.age: 200
可以看到自定义拷贝构造函数之后,两个对象不但地址不一样,成员也被我们修改了。
- 对象作为参数传递
class Student {
public:
int age;
string name;
Student(int age, string name) {
this->age = age;
this->name = name;
}
Student(const Student &student) {
cout << "拷贝构造函数" << endl;
this->age = student.age;
this->name = student.name;
}
~Student() {
cout << "析构函数" << endl;
}
};
void add(Student student) {
cout << &student << endl;
}
int main() {
Student student(18, "小红");
add(student);
cout<<&student<<endl;
}
拷贝构造函数
0xadcc9ffb10
析构函数
0xadcc9ffab0
析构函数
这种方式传递对象参数,会调用拷贝构造函数,main函数和add函数中的student为两个对象
- 解决对象传递拷贝对象问题
使用引用的方式,类似Java的对象参数传递一样
void add(Student & student) {
cout << &student << endl;
}
int main() {
Student student(18, "小红");
add(student);
cout<<&student<<endl;
}
0x488a7ffba0
0x488a7ffba0
析构函数
main函数和add函数的student的地址一样,并且没有调用拷贝构造函数。
6、常量指针、指针常量、 常量指针常量
int number = 9;
int number2 = 8;
// 大道至简 一分钟搞定
// 常量指针
const int * numberP1 = &number;
// *numberP1 = 100; // 报错,不允许去修改【常量指针】存放地址所对应的值
// numberP1 = &number2; // OK,允许重新指向【常量指针】存放的地址
// 指针常量
int* const numberP2 = &number;
*numberP2 = 100; // OK,允许去修改【指针常量】存放地址所对应的值
// numberP2 = &number2; // 报错,不允许重新指向【指针常量】存放的地址
// 常量指针常量
const int * const numberP3 = &number;
// *numberP3 = 100; // 报错,不允许去修改【常量指针常量】存放地址所对应的值
// numberP3 = &number2; // 报错,不允许重新指向【常量指针常量】存放的地址
- 常量指针
不允许去修改【常量指针】存放地址所对应的值、允许重新指向【常量指针】存放的地址 - 指针常量
允许去修改【指针常量】存放地址所对应的值、不允许重新指向【指针常量】存放的地址 - 常量指针常量
不允许去修改【常量指针常量】存放地址所对应的值、不允许重新指向【常量指针常量】存放的地址
7、深拷贝和浅拷贝
- 浅拷贝
/**
* 自定义拷贝构造函数 - 浅拷贝
* @param student 常量引用
*/
Student::Student(const Student &student) {
cout << "qian kao bei gou zhao hanshu" << endl;
this->age = student.age + 100;
this->name = "hello world";
// 浅拷贝
this->sex = student.sex;
}
- 深拷贝
/**
* 自定义拷贝构造函数 -深拷贝
* @param student 常量引用
*/
Student::Student(const Student &student) {
cout << "shen kao bei gou zhao hanshu" << endl;
this->age = student.age + 100;
this->name = "hello world";
//深拷贝
this->sex = (char *) malloc(sizeof(char *) * 10);
strcpy(this->sex, student.sex);
}
所谓的浅拷贝和深拷贝,就是在定义拷贝函数中,拷贝过来的属性是直接通过 = 号赋值的方式,还是另外在堆空间开辟内存,通过拷贝的方式。前者就是浅拷贝,后者则为深拷贝。
主要用途:
当我们的类中的成员属性是通过malloc在堆空间开辟过来的,如果我们使用浅拷贝,这样两个对象中的这个成员都指向同一块堆空间,这样一来在析构函数中手动释放对象中的成员的时候就会造成重复释放两次同一块堆空间,在一般平台下都会报错,因此这个时候我们就需要使用到深拷贝。使得拷贝之后两个对象的同一个成员,都指向不同的堆空间。
网友评论