C++-02、命名空间、构造函数、析构函数
2022-07-27 本文已影响0人
喂_balabala
命名空间
#include <iostream>
// 声明std,我们的main函数就可以直接使用里面的成员,不需要使用 std::
using namespace std; // C++自己的命名空间 (C# .net 命名空间)
// 自定义命名空间
namespace derry1 {
int age = 33;
char * name = "Derry猛男1";
void show() {
cout << "name:" << name << ", age:" << age << endl;
}
void action() {
cout << "derry1 action" << endl;
}
}
// TODO ------ 命名空间里面重复的函数
// 自定义命名空间
namespace derry2 {
void action() {
cout << "derry2 action" << endl;
}
}
// TODO ------ 小概率会遇到的情况,命名空间的嵌套
// 自定义命名空间
namespace derry3 {
namespace derry3Inner {
namespace derry3Inner1 {
namespace derry3Inner2 {
namespace derry3Inner3 {
void out() {
cout << "爱恨情仇人消瘦,悲欢起落人寂寞" << endl;
}
}
}
}
}
}
// 声明各个写的 命名空间
// using namespace derry1;
int main() {
cout << "命名空间" << endl;
// 声明各个写的 命名空间
using namespace derry1;
int ageValue = derry1::age; // 方式1 使用 刚刚声明的命名空间
derry1::show(); // 使用 刚刚声明的命名空间
ageValue = age; // 方式2 直接去引出来 ::
show(); // 直接去引出来 ::
// TODO ------ 命名空间里面重复的函数
using namespace derry2;
// action(); 很尴尬
derry1::action();
derry2::action();
// TODO ------ 小概率会遇到的情况,命名空间的嵌套
// 第一种方式 先声明命名空间 再使用
using namespace derry3::derry3Inner::derry3Inner1::derry3Inner2::derry3Inner3;
// 再使用
out();
// 第二种方式 直接使用
derry3::derry3Inner::derry3Inner1::derry3Inner2::derry3Inner3::out();
return 0;
}
构造函数、析构函数
#include <iostream>
#include <string.h>
using namespace std;
class Student {
// 构造函数
public:
// 空参数构造函数
Student() {
cout << "空参数构造函数" << endl;
}
// 一个参数的构造函数
// :Student(name, 87) 等价 1.调用两个参数的构造函数, 2.再调用当前函数
Student(char *name) :Student(name, 87) {
cout << "一个参数的构造函数" << endl;
this->name = name;
}
// 系统源码中是写的
// :name(name) 等价 this->name = name;
/*Student(char * name) :name(name) {
cout << "一个参数的构造函数" << endl;
}*/
// 两个参数的构造函数
Student(char *name, int age) {
// this->name = name;
// 堆区
this->name = (char *) (malloc(sizeof(char *) * 10));
strcpy(this->name, name);
this->age = age;
cout << "两个参数的构造函数" << endl;
}
// 析构函数 Student对象的,临终遗言,Student对象被回收了,你做一些释放工作
// delete stu 的时候,我们的析构函数一定执行
// free不会执行析构函数,也意味着,你没法在析构函数里面,做释放工作, malloc也不会调用构造函数
~Student() {
cout << "析构函数" << endl;
// 必须释放 堆区开辟的成员
if (this->name) {
free(this->name);
this->name = NULL; // 执行NULL的地址,避免出现悬空指针
}
}
// 私有属性
private:
char *name;
int age;
// 公开的 set get 函数
public:
int getAge() {
return this->age;
}
char *getName() {
return this->name;
}
void setAge(int age) {
this->age = age;
}
void setName(char *name) {
this->name = name;
}
};
int main() {
// TODO =========== 下面是栈区 开辟空间的
/*Student stu; // 调用 空参数构造函数
stu.setAge(34);
stu.setName("李元霸");
cout << "name:" << stu.getName() << ", age:" << stu.getAge() << endl;*/
// Student stu("雄霸", 30);
/*Student stu("李连杰");
cout << "name:" << stu.getName() << ", age:" << stu.getAge() << endl;*/
// TODO =========== 下面是堆区 开辟空间的 堆区必须手动释放,否则内存占用越来
// 系统源码中,会看到,很多使用 new 关键字
// *stu ->:调用一级指针的成员
// new/delete
// C++中,必须使用 new/delete 一套
Student *stu = new Student("杜子腾", 26);
cout << "name:" << stu->getName() << ", age:" << stu->getAge() << endl;
delete stu;
// free(stu); 这样写是不规范的,不按人家规则来
// 还有人这样写 (C工程师,搞了六年,改不了自己的习惯, malloc)
// malloc 你的构造函数都没有调用,这个不行的
/*Student *stu2 = (Student*) malloc(sizeof(Student));
free(stu2);*/
// 纠结:C++有析构函数(临终遗言 释放工作) Java KT 临终遗言 是什么?
return 0;
}
Java/KT的所谓的析构函数
package test;
import java.io.Closeable;
import java.io.IOException;
// 隐式 extends Object
public class JavaHelp implements Closeable {
@Override
protected void finalize() throws Throwable {
super.finalize();
close();
}
@Override
public void close() throws IOException {
}
}
package test;
// 默认隐式 extends Object
public class Stu {
// 并不是说,Java调用了finalize函数,代表这个类可能被回收了(只是回收的前兆)
// 此类加入到queue队列中,等待虚拟机来处理(只有虚拟机处理回收了,才叫回收)
@Override
protected void finalize() throws Throwable {
super.finalize();
System.out.println("Java 我被回收了");
}
}
package test
// 隐式的 : Any?
// KT做不到,但是可以借助Java来做
class Student : JavaHelp() {
override fun close() {
super.close()
println("KT 我被回收了");
}
}
package test;
public class Main {
public static void main(String[] aaa) {
// ====== Java 回收
Stu stu = new Stu();
stu = null;
System.gc(); // (如果没有stu = null)gc机制来扫描吧,gc一过来发现,stu还有指向,扫你妹啊
// ===== KT 回收
Student student = new Student();
student = null;
System.gc();;
}
}
new/delete 是一套 会调用构造函数 与 析构函数 【C++标准规范】
malloc/free是一套 不调用构造函数 与 析构函数 【C的范畴,虽然不推荐,但是也是可以的】
拷贝构造函数
#include <iostream>
#include <string.h>
using namespace std;
class Student {
public:
Student() { cout << "空参数构造函数" << endl; }
// 两个参数的构造函数
Student(char *name, int age) : name(name), age(age) {
cout << "两个参数构造函数" << endl;
}
// 析构函数
// ~Student(char * name) { } 这样写,就不是析构函数了,如果你这样写,C/C++编译器对你很无语
~Student() {
cout << "析构函数" << endl;
}
// 以前是默认有一个拷贝构造函数,stu2 = stu1 默认赋值 【隐式 你看不到】
// 拷贝构造函数,它默认有,我们看不到,一旦我们写拷贝构造函数,会覆盖她
// 对象1 = 对象2
// 覆盖拷贝构造函数
Student(const Student & student) { // 常量引用:只读的,不让你修改
cout << "拷贝构造函数" << endl;
// 我们自己赋值
// 为什么要自己赋值,自己来控制,就可以 例如:-10
this->name = student.name;
this->age = student.age - 10;
cout << "自定义拷贝构造函数 内存地址 " << &student << endl;
}
// 私有属性
private:
char *name;
int age;
// 公开的 set get 函数
public:
int getAge() {
return this->age;
}
char *getName() {
return this->name;
}
void setAge(int age) {
this->age = age;
}
void setName(char *name) {
this->name = name;
}
};
struct Person {
int age;
char *name;
};
// TODO = 号的意义 隐式代码,引出 拷贝构造函数
/*
int main() {
Person person1 = {100, "张三丰"};
// = 你看起来,没有什么特殊,隐式的代码:你看不到 C/C++编译器 会把p1的成员值赋值给p2成员
Person person2 = person1;
cout << &person1 << endl;
cout << &person2 << endl;
cout << person2.name << ", " << person2.age << endl;
// 思考:对象 对象1=对象2 默认的 拷贝构造函数
return 0;
}*/
// TODO 拷贝构造函数
/*
int main() {
Student stu1("李鬼", 34);
Student stu2 = stu1;
cout << stu2.getName() << " , " << stu2.getAge() << endl;
cout << "main " << &stu1 << endl; // 这里地址的打印和拷贝构造函数里地址的打印是一样的, 注意:cnetos的环境 地址打印有差异,要注意
// TODO 拷贝构造函数的注意点:
// Student stu1("李鬼", 34);
// Student stu2;
// stu2 = stu1; // 这样赋值是不会调用自定义拷贝构造函数的,但是会调用默认赋值
// Student stu2 = stu1; // 这样赋值是会调用自定义拷贝构造函数,我们自己赋值
// cout << stu2.getName() << " , " << stu2.getAge() << endl;
getchar(); // 程序等待在这一行
return 0;
} // main函数弹,stu1栈成员会回收 stu2栈成员会回收
*/
// TODO 这种写法 拷贝构造函数 到底会不会调用
int main() {
Student *student1 = new Student("杜子腾", 39);
Student *student2 = student1; // 压根就不会执行拷贝构造函数(指针指向问题,和我们刚刚那个 对象2=对象1 是两回事)
student2->setAge(99);
cout << student1->getName() << student1->getAge() << endl;
// “->”调用一级指针的成员 和 “.”非指针的操作 有啥区别
return 0;
}
Student *student1 = new Student("杜子腾", 39); Student *student2 = student1;为什么不走拷贝构造函数?
- 因为student1是new出来的,在堆区。2赋值给1只是把地址赋值过去。