diff --git a/README.md b/README.md index 794b4d3..12b8932 100644 --- a/README.md +++ b/README.md @@ -5,3 +5,5 @@ #### day1: C++简介, ::作用域, namespace 命名空间, using 声明, using 编译指令, 类型转换, struct 类型加强, bool 关键字, 三目运算符增强, const 增强 #### day2: const 和#define 的区别, 引用(reference) 【重要】, 内联函数, 函数的默认值参数, 函数的占位参数, 函数重载和 extern "c", 类与对象的概念, 面向对象程序设计案例 + +#### day3: 对象的构造与析构, 构造函数的分类与调用, 拷贝构造函数的调用时机, 构造函数的调用规则, 深拷贝和浅拷贝, 多个对象的构造和析构(初始化列表, 类对象作为成员), explicit 关键字(禁止隐式转换), 动态创建对象(malloc/realloc/calloc 在堆中创建空间, new 关键字), 扩展 new 和 delete, diff --git a/day3/d1.cpp b/day3/d1.cpp new file mode 100644 index 0000000..f178712 --- /dev/null +++ b/day3/d1.cpp @@ -0,0 +1,74 @@ +// 对象的构造与析构 +#include +#include +#include + +using namespace std; + +class Animal +{ +public: + Animal(); + Animal(const char *name, const char *food); + ~Animal(); // 析构函数(对象回收时,清理资源) + +public: + void eat(); + void say(const char *msg); + +private: + char *name, *food; +}; + +Animal::Animal() +{ + name = (char *)malloc(32); + food = (char *)malloc(32); + strcpy(name, "小动物"); + strcpy(food, "水"); +} + +Animal::Animal(const char *name, const char *food) +{ + this->name = (char *)malloc(32); + this->food = (char *)malloc(32); + strcpy(this->name, name); + strcpy(this->food, food); +} + +Animal::~Animal() +{ + cout << name << "空间回收" << endl; + + // 回收在构造函数(初始化)中动态分配的空间 + free(name); + free(food); +} + +void Animal::eat() +{ + cout << name << "吃: " << food << endl; +} + +void Animal::say(const char *msg) +{ + cout << name << "遇到主人: " << msg << endl; +} + +int main() +{ + // 尽量使用堆空间创建类的对象: 使用 类指针 和 new 关键字 + Animal *anm1 = new Animal(); + anm1->eat(); + + // 使用栈空间的情况 + Animal anm2; + anm2.say("小浣熊"); + + // 使用括号 + Animal anm3("小黄", "肉"); + anm3.eat(); + anm3.say("旺旺..."); + + return 0; +} diff --git a/day3/d10.cpp b/day3/d10.cpp new file mode 100644 index 0000000..cd5ea1e --- /dev/null +++ b/day3/d10.cpp @@ -0,0 +1,60 @@ +// 深拷贝和浅拷贝 +// 深拷贝举例 +#include +#include +#include + +using namespace std; + +class Person +{ +private: + char *name; + int age; + +public: + Person(const char *name, int age) + { + this->name = (char *)malloc(32); + strcpy(this->name, name); + this->age = age; + } + Person(const Person &obj) // 深拷贝,重写构造方法 + { + this->name = (char *)malloc(32); + strcpy(this->name, obj.name); + this->age = obj.age; + } + ~Person() + { + if (name != NULL) + { + free(name); + } + } + +public: + void setName(char *name) + { + strcpy(this->name, name); + } + void show() + { + cout << this << " " << name << ", " << age << endl; + } +}; + +int main() +{ + Person p1("disen", 20); + Person p2 = p1; + p2.setName("lucy"); + Person p3 = Person(p2); + p3.setName("Jack"); + + p1.show(); + p2.show(); + p3.show(); + + return 0; +} diff --git a/day3/d11.cpp b/day3/d11.cpp new file mode 100644 index 0000000..9422142 --- /dev/null +++ b/day3/d11.cpp @@ -0,0 +1,27 @@ +// 多个对象的构造和析构 +// 初始化列表 +#include + +using namespace std; + +class A +{ +private: + int x, y, z; + // char *name; + string name; // char * 建议替换为 string + +public: + A(int x, int y, int z, const string &name) : x(x), y(y), z(z), name(name) {} + void show() + { + cout << x << ", " << y << ", " << z << ", " << name << endl; + } +}; + +int main() +{ + A a1(10, 20, 4, "disen"); + a1.show(); + return 0; +} diff --git a/day3/d12.cpp b/day3/d12.cpp new file mode 100644 index 0000000..971fcd6 --- /dev/null +++ b/day3/d12.cpp @@ -0,0 +1,48 @@ +// 多个对象的构造和析构 +// 类对象作为成员 +#include + +using namespace std; + +class A +{ +public: + A() + { + cout << "A()" << endl; + } + A(int x) + { + cout << "A(int x)" << endl; + } + ~A() + { + cout << "~A()" << endl; + } +}; + +class B +{ +public: + B() // 构造函数用于初始化成员数据,说明成员变量先创建 + { + cout << "B()" << endl; + } + B(int x) + { + cout << "B(int x)" << endl; + } + ~B() // A 的对象在 B 的空间中,A 对象在 B 空间释放之后就失效,失效也会释放空间(调用析构函数) + { + cout << "~B()" << endl; + } + +private: + A a; // A 类的对象作为 B 类的成员 +}; + +int main() +{ + B b1; + return 0; +} diff --git a/day3/d13.cpp b/day3/d13.cpp new file mode 100644 index 0000000..c8479fb --- /dev/null +++ b/day3/d13.cpp @@ -0,0 +1,50 @@ +// 多个对象的构造和析构 +// 类对象作为成员 +// d12 的改造测试 +#include + +using namespace std; + +class A +{ +public: + A() + { + cout << "A()" << endl; + } + A(int x) + { + cout << "A(int x)" << endl; + } + ~A() + { + cout << "~A()" << endl; + } +}; + +class B +{ +public: + B() // 构造函数用于初始化成员数据,说明成员变量先创建 + { + cout << "B()" << endl; + } + // 成员名:(参数名) + B(int x) : a(x) // 指定 a 对象的构造函数进行数据初始化 + { + cout << "B(int x)" << endl; + } + ~B() // A 的对象在 B 的空间中,A 对象在 B 空间释放之后就失效,失效也会释放空间(调用析构函数) + { + cout << "~B()" << endl; + } + +private: + A a; // A 类的对象作为 B 类的成员 +}; + +int main() +{ + B b1(1); + return 0; +} diff --git a/day3/d14.cpp b/day3/d14.cpp new file mode 100644 index 0000000..246d086 --- /dev/null +++ b/day3/d14.cpp @@ -0,0 +1,43 @@ +// explicit 关键字(禁止隐式转换) +#include + +using namespace std; + +class Person +{ +private: + int age; + string name; + +public: + Person(const char *name, int age = 18) + { + this->name = name; + this->age = age; + } + // explicit 使得不存在从 "int" 转换到 "Person" 的适当构造函数 + explicit Person(int age) // 进制 Person p = 值 + { + this->age = age; + this->name = "disen"; + } + +public: + void show() + { + cout << name << ", " << age << endl; + } +}; + +int main() +{ + Person p1 = "jack"; + Person p2 = Person("doken", 9); + Person p3 = Person(1); + // Person p4 = 2; // 不存在从 "int" 转换到 "Person" 的适当构造函数 + p1.show(); + p2.show(); + p3.show(); + + return 0; +} diff --git a/day3/d15.cpp b/day3/d15.cpp new file mode 100644 index 0000000..39c629a --- /dev/null +++ b/day3/d15.cpp @@ -0,0 +1,51 @@ +// 动态创建对象(malloc / realloc / calloc 在堆中创建空间, new 关键字) +#include +#include + +using namespace std; + +class A +{ +private: + int x; + +public: + A(int x) + { + this->x = x; + cout << "A(int)" << endl; + } + ~A() + { + cout << "~A()" << endl; + } + +public: + void init(int x) + { + this->x = x; + cout << "init(int)" << endl; + } + void clean() + { + cout << "clean()" << endl; + } +}; + +int main() +{ + // 1) 使用 malloc 方式创建 + // cout << "A size is " << sizeof(A) << endl; + // A *a1 = (A *)malloc(sizeof(A)); + // // a1->A(20); // 不允许显式调用构造函数 + // a1->init(20); // 初始化数据 + // a1->clean(); // 释放数据的空间 + // a1->~A(); // 析构函数可以显式调用 + // free(a1); + + // 2) new 方式创建,delete释放 + A *a1 = new A(1); + delete a1; // 用完之后直接 delete 释放空间 + + return 0; +} diff --git a/day3/d16.cpp b/day3/d16.cpp new file mode 100644 index 0000000..130d51e --- /dev/null +++ b/day3/d16.cpp @@ -0,0 +1,23 @@ +// 扩展 new 和 delete +// 数组的 new 和 delete +#include + +using namespace std; + +int main() +{ + // 使用拓展的 new 创建类对象数组 + int *p = new int[6]{1, 2, 3, 4, 5, 6}; + for (int i = 0; i < 10; i++) + { + cout << *(p + i) << endl; + } + delete[] p; // 释放数组空间 + + cout << "--------------------" << endl; + for (int i = 0; i < 10; i++) + { + cout << *(p + i) << endl; + } + return 0; +} diff --git a/day3/d17.cpp b/day3/d17.cpp new file mode 100644 index 0000000..5431626 --- /dev/null +++ b/day3/d17.cpp @@ -0,0 +1,43 @@ +#include +#include + +using namespace std; + +class A +{ +private: + string name; + +public: + A() + { + cout << "A()" << endl; + name = "no name"; + } + A(const string &name) + { + cout << "A(const string &name)" << endl; + this->name = name; + cout << "name: " << name << endl; + } + ~A() + { + cout << name << "~A()" << endl; + } +}; + +int main() +{ + // A *p = new A[5]; + // delete[] p; + // A *p2 = new A[4]{A("a"), A("b"), A("c"), A("d")}; + // delete[] p2; // 释放数组中成员对象时,从高(地址)到低(地址)依次释放 + + A *a = new A("abc"); + free(a); // 只是放指针指向的堆空间,不会调用对象的析构函数 + + char *a2 = (char *)malloc(sizeof(A)); + delete a2; // 可以删除简单的 void* 指针 + + return 0; +} diff --git a/day3/d2.cpp b/day3/d2.cpp new file mode 100644 index 0000000..98617f0 --- /dev/null +++ b/day3/d2.cpp @@ -0,0 +1,35 @@ +// 构造函数的分类与调用 +// 拷贝构造函数 +#include + +using namespace std; + +class A +{ + +public: + int x; + +public: + A() {} + A(A &other) // 拷贝构造函数 + { + this->x = other.x; + } +}; + +int main() +{ + A a1; // 调用无参的构造函数进行初始化 a1 对象 + a1.x = 10; + cout << "a1 x = " << a1.x << endl; + + A a2(a1); // 使用拷贝构造 + cout << "a2 x = " << a2.x << endl; + + A *a3 = new A(); // 使用指针和new,在堆空间创建对象 + // a3->x = 20; + cout << "a3 x = " << a3->x << endl; + + return 0; +} diff --git a/day3/d3.cpp b/day3/d3.cpp new file mode 100644 index 0000000..624b54c --- /dev/null +++ b/day3/d3.cpp @@ -0,0 +1,44 @@ +// 构造函数的分类与调用 +#include + +using namespace std; + +class B +{ +private: + int n; + +public: + // B() { cout << "B()" << endl; } + B(int n) + { + cout << "B(int n)" << endl; + this->n = n; + } + B(const B &other) + { + cout << "B(B &other)" << endl; + this->n = other.n; + } + +public: + void showN() + { + cout << "n = " << n << endl; + } +}; + +int main() +{ + B b1 = 20; // 隐式调用 B(int n), B(20), 只创建一个对象 + + B b2 = B(30); // 显式调用 B(int n) + + B b3 = b2; // 隐式调用 B(B &other) + + B &b4 = b3; // 不会创建空间,只是一个别名 + + B b5(b4); // 显式调用 B(B &other) + + return 0; +} diff --git a/day3/d4.cpp b/day3/d4.cpp new file mode 100644 index 0000000..a19e123 --- /dev/null +++ b/day3/d4.cpp @@ -0,0 +1,56 @@ +// 构造函数的分类与调用 +#include +#include + +using namespace std; + +class C +{ +private: + int x, y; + +public: + C(int x) + { + this->x = x; + } + C(int x, int y) + { + this->x = x; + this->y = y; + } + C(const C &other) + { + this->x = other.x; + this->y = other.y; + } + void show() + { + cout << "x = " << x << ", y = " << y << endl; + } + ~C() + { + cout << this << "释放资源" << endl; + } +}; + +int main() +{ + cout << "C(0,1) 之前" << endl; + C(0, 1); // 匿名创建的类对象,创建完后就直接释放了 + cout << "C(0,1) 之后" << endl; + + C c1(1, 2); + c1.show(); + C c2 = (1, 5); // 使用单参数构造函数 C(int x), 然后将其改为 ", 运算" 后面的值 + // C c2 = 1; + c2.show(); + C c3 = C(3, 4); + c3.show(); + C c4(c3); + c4.show(); + C &c5 = c4; + c5.show(); + + return 0; +} diff --git a/day3/d5.cpp b/day3/d5.cpp new file mode 100644 index 0000000..0abd131 --- /dev/null +++ b/day3/d5.cpp @@ -0,0 +1,54 @@ +// 创建类对象的指针 +#include +#include +#include + +using namespace std; + +class A +{ +public: + char *msg; + +public: + A() + { + this->msg = (char *)malloc(30); + strcpy(this->msg, "haha"); + } + A(const char *msg) + { + this->msg = (char *)malloc(30); + strcpy(this->msg, msg); + } + ~A() + { + cout << this << "release msg : " << this->msg << endl; + free(this->msg); + // free(this); + } +}; + +int main() +{ + A *a1 = new A; + cout << "a1->msg: " << a1->msg << endl; + + A *a2 = new A("disen 666"); + cout << "a2->msg: " << a2->msg << endl; + + // 【注意】指针释放空间时, 不会自动执行对象的析构函数 + // 可以通过手动调用 对象的析构方法 或使用 delete + a1->~A(); + free(a1); + // a2->~A(); + // delete a1; + delete a2; + + A a3; + // 注意: delete 只能删除 new 出来的对象,即对象的指针 + // A &a4 = a3; + // delete &a4; + + return 0; +} diff --git a/day3/d6.cpp b/day3/d6.cpp new file mode 100644 index 0000000..dd1bf34 --- /dev/null +++ b/day3/d6.cpp @@ -0,0 +1,57 @@ +// 拷贝构造函数的调用时机 +// 编译器优化,不会调用拷贝构造函数,而是直接创建一个返回值的引用 +#include + +using namespace std; + +class A +{ +public: + int x = 0; + +public: + A() + { + cout << this << " A()" << endl; + } + A(const A &other) + { + this->x = other.x; + cout << this << " A(const A &other)" << endl; + } + ~A() + { + cout << this << " ~A()" << endl; + } +}; + +void test1(A a) // ?是否调用拷贝构造函数 +{ + cout << "test1(A a) a.x = " << a.x << endl; + + // 当函数结束时,a 释放,会调用析构函数 +} + +A test2() +{ + A a1; // 局部的类对象, 没有执行拷贝构造函数 + a1.x = 1; + cout << "test2() a1.x = " << a1.x << endl; + return a1; // 释放局部对象 a1 +} + +void test3() +{ + A a2 = test2(); // 返回 A 类的对象,没有调用拷贝构造函数,只是创建了一个 test2() 返回值的引用 + cout << "test3() a2.x = " << a2.x << endl; +} + +int main() +{ + A a0; + // test1(a0); // 作为值传递,调用拷贝构造函数 + + test3(); + cout << "over" << endl; + return 0; +} diff --git a/day3/d7.cpp b/day3/d7.cpp new file mode 100644 index 0000000..096bf16 --- /dev/null +++ b/day3/d7.cpp @@ -0,0 +1,60 @@ +// 拷贝构造函数的调用时机 +// 编译器优化,不会调用拷贝构造函数,而是直接创建一个返回值的引用 +#include + +using namespace std; + +class A +{ +public: + int x = 0; + +public: + A() + { + cout << this << " A()" << endl; + } + A(const A &other) + { + this->x = other.x; + cout << this << " A(const A &other)" << endl; + } + ~A() + { + cout << this << " ~A()" << endl; + } +}; + +void test1(A &a) // ?是否调用拷贝构造函数 +// void test1(A a) // ?是否调用拷贝构造函数 +{ + cout << "test1(A a) a.x = " << a.x << endl; + + // 当函数结束时,a 释放,会调用析构函数 +} + +A test2() // 不要声明为 A &test2(), 因为返回对象时,会释放局部对象,导致返回的引用指向一个已经释放的对象 +{ + A a1; // 局部的类对象, 没有执行拷贝构造函数 + a1.x = 1; + cout << "test2() a1.x = " << a1.x << endl; + return a1; // 释放局部对象 a1 +} + +void test3() +{ + cout << "tsss = " << endl; + + A a2 = test2(); // 返回 A 类的对象,没有调用拷贝构造函数,只是创建了一个 test2() 返回值的引用 + cout << "test3() a2.x = " << a2.x << endl; +} + +int main() +{ + A a0; + test1(a0); // 作为值传递,调用拷贝构造函数 + + // test3(); + cout << "over" << endl; + return 0; +} diff --git a/day3/d8.cpp b/day3/d8.cpp new file mode 100644 index 0000000..2faf12b --- /dev/null +++ b/day3/d8.cpp @@ -0,0 +1,30 @@ +// 构造函数的调用规则 +#include + +using namespace std; + +class A +{ +public: + int x, y; + void show() + { + cout << this << " x = " << x << ", y = " << y << endl; + } +}; + +int main() +{ + A a1; + // A a2 = a1; // 自动调用拷贝构造函数 A(const A&obj) + + a1.x = 20; + A a2 = a1; // 自动调用拷贝构造函数 A(const A&obj) + + a1.y = 30; + // A a2 = a1; // 自动调用拷贝构造函数 A(const A&obj) + + a1.show(); // 20,30 浅拷贝 + a2.show(); // + return 0; +} diff --git a/day3/d9.cpp b/day3/d9.cpp new file mode 100644 index 0000000..7e8bcf1 --- /dev/null +++ b/day3/d9.cpp @@ -0,0 +1,51 @@ +// 深拷贝和浅拷贝 +// 浅拷贝举例 +#include +#include +#include + +using namespace std; + +class Person +{ +private: + char *name; + int age; + +public: + Person(const char *name, int age) + { + this->name = (char *)malloc(32); + this->age = age; + } + void release_name_pointer() + { + free(name); + } + +public: + void setName(char *name) + { + strcpy(this->name, name); + } + void show() + { + cout << name << ", " << age << endl; + } +}; + +int main() +{ + Person p1("disen", 20); + Person p2 = p1; + Person p3 = Person(p2); + p3.setName("Jack"); + + p1.show(); + p2.show(); + p3.show(); + + // p1.release_name_pointer(); + p2.release_name_pointer(); + return 0; +}