From aae9aba049f532877a3699ee7c392d2cab18c7bf Mon Sep 17 00:00:00 2001 From: flykhan Date: Tue, 1 Aug 2023 18:51:53 +0800 Subject: [PATCH] =?UTF-8?q?day7:=20=E7=B1=BB=E6=A8=A1=E7=89=88?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- day7/d1.cpp | 44 +++++++++++++++++++++++ day7/d10.cpp | 35 ++++++++++++++++++ day7/d11.cpp | 45 +++++++++++++++++++++++ day7/d12.cpp | 42 ++++++++++++++++++++++ day7/d13.cpp | 92 +++++++++++++++++++++++++++++++++++++++++++++++ day7/d14.cpp | 31 ++++++++++++++++ day7/d15.cpp | 42 ++++++++++++++++++++++ day7/d16.cpp | 71 ++++++++++++++++++++++++++++++++++++ day7/d17.cpp | 42 ++++++++++++++++++++++ day7/d18.cpp | 39 ++++++++++++++++++++ day7/d2.cpp | 40 +++++++++++++++++++++ day7/d3.cpp | 53 +++++++++++++++++++++++++++ day7/d4.cpp | 55 ++++++++++++++++++++++++++++ day7/d5.cpp | 46 ++++++++++++++++++++++++ day7/d6.cpp | 37 +++++++++++++++++++ day7/d7.cpp | 47 ++++++++++++++++++++++++ day7/d8.cpp | 44 +++++++++++++++++++++++ day7/d9/MyPoint.h | 30 ++++++++++++++++ day7/d9/main.cpp | 14 ++++++++ 19 files changed, 849 insertions(+) create mode 100644 day7/d1.cpp create mode 100644 day7/d10.cpp create mode 100644 day7/d11.cpp create mode 100644 day7/d12.cpp create mode 100644 day7/d13.cpp create mode 100644 day7/d14.cpp create mode 100644 day7/d15.cpp create mode 100644 day7/d16.cpp create mode 100644 day7/d17.cpp create mode 100644 day7/d18.cpp create mode 100644 day7/d2.cpp create mode 100644 day7/d3.cpp create mode 100644 day7/d4.cpp create mode 100644 day7/d5.cpp create mode 100644 day7/d6.cpp create mode 100644 day7/d7.cpp create mode 100644 day7/d8.cpp create mode 100644 day7/d9/MyPoint.h create mode 100644 day7/d9/main.cpp diff --git a/day7/d1.cpp b/day7/d1.cpp new file mode 100644 index 0000000..e8d1df0 --- /dev/null +++ b/day7/d1.cpp @@ -0,0 +1,44 @@ +#include +#include +#include + +using namespace std; + +template +T &maxVal(T &a, T &b) +{ + return a > b ? a : b; +} + +class A +{ + friend A &maxVal(A &a, A &b); // 模板特化的友元函数,用于访问私有成员 + +private: + int x; + +public: + A(int x) : x(x) {} + void show() + { + cout << "x = " << x << endl; + } +}; + +// 具体化函数模版的重载 +template <> +A &maxVal(A &a, A &b) // 模板特化 +{ + if (a.x > b.x) + return a; + return b; +} + +int main() +{ + A a1(20), a2(50); + // A &b = maxVal(a1, a2); + A &b = maxVal(a1, a2); + b.show(); + return 0; +} diff --git a/day7/d10.cpp b/day7/d10.cpp new file mode 100644 index 0000000..f2fde1f --- /dev/null +++ b/day7/d10.cpp @@ -0,0 +1,35 @@ +// 模版类与友元 +#include +#include +#include + +using namespace std; + +template +class A +{ + // 内部实现的友元函数(全局性的友元函数,类的外部可以直接访问 showIn(x) ,不需要类对象调用 a.showIn()) + // 接收当前模版类的引用时,可以指定当前模版类的类型 + friend void showIn(A &a) + { + cout << a.item << endl; + } + +private: + T item; + +public: + A(T item) + { + this->item = item; + } + + // public: +}; + +int main() +{ + A a(20); + showIn(a); + return 0; +} diff --git a/day7/d11.cpp b/day7/d11.cpp new file mode 100644 index 0000000..f0a167c --- /dev/null +++ b/day7/d11.cpp @@ -0,0 +1,45 @@ +// 模版类与友元 +// 外部实现的友元函数 +// 是函数模板时,必须在类定义之前声明。在类中声明友元全局函数时,必须使用<> 空泛型表示此函数是函数模板。 + +#include +#include +#include + +using namespace std; + +template +class A; +template +void showOut(A &a); + +template +class A +{ + // 外部实现的友元函数,它有自己的模版类型,不需要指定当前模版类的类型 + // <>空泛型表示外部是函数模版,模版的泛型同当前类的泛型 + // 要求: 必须之前先声明此函数为构造函数 + friend void showOut<>(A &a); + +private: + T item; + +public: + A(T item) + { + this->item = item; + } +}; + +template +void showOut(A &a) // 全局友元函数 +{ + cout << "out item is: " << a.item << endl; +} + +int main() +{ + A a(30); + showOut(a); + return 0; +} diff --git a/day7/d12.cpp b/day7/d12.cpp new file mode 100644 index 0000000..402a710 --- /dev/null +++ b/day7/d12.cpp @@ -0,0 +1,42 @@ +// 友元函数模板 +/* +格式 : +template +friend 返回值类型 函数名(T &参数名); + */ +#include +using namespace std; + +template +class A +{ + // 友元函数模板,声明的友元函数名不需要加<>空泛型 + template + friend void show(A &a); + +private: + T item; + +public: + A(T item) + { + this->item = item; + } +}; + +template +void show(A &a) +{ + cout << "template friend item is: " << a.item << endl; +} + +int main() +{ + A a(15); + show(a); + + A b(15.5); + show(b); + + return 0; +} \ No newline at end of file diff --git a/day7/d13.cpp b/day7/d13.cpp new file mode 100644 index 0000000..a843db1 --- /dev/null +++ b/day7/d13.cpp @@ -0,0 +1,92 @@ +// 类模板的应用 +// 设计一个数组模板类(MyArray),完成对不同类型元素的管理 +#include +#include +#include + +using namespace std; + +template +class MyArray +{ +private: + int index; // 当前元素的位置 + T *arr; // 指向数组的指针 + int capacity; // 最大容量 + int size; // 当前容量 + +public: + MyArray(int capacity) + { + this->capacity = capacity; // 最大容量 + this->size = 0; // 当前容量为0 + this->index = 0; // 当前元素位置为0 + this->arr = new T[capacity]; // 申请内存 + } + MyArray(const MyArray &other) + { + this->index = other.index; // 当前元素的位置 + this->capacity = other.capacity; // 最大容量 + this->arr = new T[this->capacity]; // 申请内存 + for (int i = 0; i <= this->capacity; i++) + { + this->arr[i] = other.arr[i]; // 拷贝数据 + } + this->size = other.size; // 当前容量 + } + ~MyArray() + { + delete[] this->arr; // 释放内存 + } + +public: + T &get(int index) + { + return arr[index]; + } + T &operator[](int index) + { + return arr[index]; + } + // & 是为了链式编程 + MyArray &push(T item) + { + if (index < capacity) + { + arr[index++] = item; // 将元素放入数组 + size++; // 当前容量加1 + } + return *this; + } + T pop() + { + if (index > 0) + { + size--; // 当前容量减1 + return arr[--index]; + } + else + return NULL; + } + int getSize() + { + return size; + } +}; + +int main() +{ + MyArray a1 = MyArray(20); + a1[0] = 10; + a1[1] = 20; + MyArray a2 = a1; + cout << "a2[0] = " << a2[0] << ", a2[1] = " << a2[1] << endl; + + a1.push(30).push(40).push(50); + for (int i = 0; i <= 3; i++) + { + cout << a1.pop() << endl; + } + + return 0; +} diff --git a/day7/d14.cpp b/day7/d14.cpp new file mode 100644 index 0000000..dd4b5c8 --- /dev/null +++ b/day7/d14.cpp @@ -0,0 +1,31 @@ +// 类型转换 + +#include + +using namespace std; + +int test1() +{ + float f = 97.5; + char c = static_cast(f); + cout << "c = " << (int)c << endl; +} + +int test2() +{ + float f = 97.5; + // int *p = &f; // 指针转换不允许跨类型 + // int *p = static_cast(&f); + // int *p = (int *)&f; + // int *p = dynamic_cast(&f); + float *pf = &f; + // double *p = const_cast(pf); + int *p = reinterpret_cast(pf); // 重新解释类型转换,不安全 + cout << "*p = " << *p << endl; +} + +int main() +{ + test2(); + return 0; +} diff --git a/day7/d15.cpp b/day7/d15.cpp new file mode 100644 index 0000000..7936cca --- /dev/null +++ b/day7/d15.cpp @@ -0,0 +1,42 @@ +// 静态类型转换 +#include +#include +#include + +using namespace std; + +class A +{ +public: + int x; + A(int x) : x(x) {} +}; + +class B : public A +{ +public: + int y; + B(int x, int y) : A(x), y(y) {} +}; + +int main() +{ + A *a = new A(5); + B *b = new B(10, 20); + + A *c = static_cast(b); // 静态上行转换,子类指针向父类指针转换 + // cout << "a.x = " << a->x << endl; + // cout << "b.x = " << b->x << ", b.y = " << b->y << endl; + // cout << "b = " << b << endl; + // cout << "c = " << c << endl; + // cout << "c.x = " << c->x << endl; + + // B *b2 = static_cast(a); // 下行转换,父类指针向子类指针转换 + // B *b2 = (B *)a; // 强制下行转换,不安全 + // cout << "b2.x = " << b2->x << ", b2.y = " << b2->y << endl; + + delete a; + delete b; + + return 0; +} diff --git a/day7/d16.cpp b/day7/d16.cpp new file mode 100644 index 0000000..a873ed3 --- /dev/null +++ b/day7/d16.cpp @@ -0,0 +1,71 @@ +// 动态类型转换 +#include + +using namespace std; + +class A +{ +protected: + int x; + +public: + A(int x) : x(x) {} + void show() + { + cout << "A x = " << x << endl; + } +}; + +class B : public A +{ +public: + B(int x) : A(x) {} + void print() + { + cout << "B print x = " << x << endl; + } +}; + +class C +{ +}; + +void test1() +{ + int a = 65; + // 动态转化不支持基本数据类型之间的转换 + // char c = dynamic_cast(a); + // char *c = dynamic_cast(&a); + // cout << "c = " << c << endl; +} + +void test2() +{ + A a1 = A(10); + B b1 = B(20); + + // 上行转换 + A &a2 = dynamic_cast(b1); + a2.show(); + // a2.print(); // 不存在 print 成员函数 + b1.print(); + + // 下行转换: 动态转换不支持(安全) + // B &b2 = dynamic_cast(a2); + // b2.print(); + B &b3 = static_cast(a2); + b3.print(); +} + +// 不相关类型的转换: 不可动态转换 +void test3() +{ + A *a = new A(20); + // C *p = dynamic_cast(a); +} + +int main() +{ + test3(); + return 0; +} diff --git a/day7/d17.cpp b/day7/d17.cpp new file mode 100644 index 0000000..1f3d4af --- /dev/null +++ b/day7/d17.cpp @@ -0,0 +1,42 @@ +// const 转换 +#include + +using namespace std; + +void change(const int *p, int value) +{ + int *q = const_cast(p); // 转换为非 const 指针 + *q = value; +} + +int main() +{ + int a = 10; + const int b = 30; // 存储在符号表,在栈中没有空间 + // 1. 将变量转化为 const 引用变量【可以】 + const int &a1 = const_cast(a); + // 2. 将变量地址转化为 const 指针变量【可以】 + const int *a2 = const_cast(&a); + + // 3. 去掉 b 的 const 修饰 + // b 在取地址时在占中开辟空间,b1 指向空间 + // int b1 = const_cast(b);【不可以】 + int &b1 = const_cast(b); + b1 = 100; + cout << "b = " << b << endl; + cout << "b1 = " << b1 << endl; + + // 4. 去掉 a2 的 const 修饰 + int *a3 = const_cast(a2); + *a3 = 200; + cout << "*a2 = " << *a2 << endl; + cout << "*a3 = " << *a3 << endl; + + // 5. 将 a3 转化为 const 指针变量【可以】 + const int *a4 = const_cast(a3); + // *a4 = 100; + cout << "*a4 = " << *a4 << endl; + cout << "*a3 = " << *a3 << endl; + + return 0; +} diff --git a/day7/d18.cpp b/day7/d18.cpp new file mode 100644 index 0000000..86d219a --- /dev/null +++ b/day7/d18.cpp @@ -0,0 +1,39 @@ +#include + +using namespace std; + +class A +{ +public: + int x; + void show() + { + cout << "A show() x = " << x << endl; + } +}; + +class B +{ +public: + int x; + void show() + { + cout << "B show() x = " << x << endl; + } +}; + +int main() +{ + A *a = new A(); + a->x = 100; + B *b = new B(); + b->x = 200; + + // B *b2 = static_cast(a); // error + // B *b3 = dynamic_cast(a); // error + B *b4 = reinterpret_cast(a); // 输出: B show() x = 100 + + b4->show(); + + return 0; +} diff --git a/day7/d2.cpp b/day7/d2.cpp new file mode 100644 index 0000000..acd8f69 --- /dev/null +++ b/day7/d2.cpp @@ -0,0 +1,40 @@ +#include +#include +#include + +using namespace std; + +template +T &maxVal(T &a, T &b) +{ + return a > b ? a : b; +} + +class A +{ +private: + int x; + +public: + A(int x) : x(x) {} + void show() + { + cout << "x = " << x << endl; + } + +public: + // 重载运算符>,解决函数模版的局限性,不用具体化函数模版 + bool operator>(const A &a) const + { + return this->x > a.x; + } +}; + +int main() +{ + A a1(20), a2(50); + // A &b = maxVal(a1, a2); + A &b = maxVal(a1, a2); + b.show(); + return 0; +} diff --git a/day7/d3.cpp b/day7/d3.cpp new file mode 100644 index 0000000..65b6552 --- /dev/null +++ b/day7/d3.cpp @@ -0,0 +1,53 @@ +// 类模版 +// 类模版是成员变量的数据类型泛化 +// 类模版的声明作用于整个类,而不是单个成员,即类的内部的任何位置都可以使用 + +// 如: 定义长方形的图形类 + +#include +#include +#include + +using namespace std; + +// 类模版 +template +class Rectangle +{ +private: + T width, height; //矩形的宽和高 + +public: + Rectangle(T w, T h) : width(w), height(h) {} + +public: + void draw() + { + cout << "绘制矩形" + << "宽: " << width << "高: " << height << endl; + } + void length() + { + cout << "矩形周长: " << 2 * (width + height) << endl; + } +}; + +int main() +{ + cout << "r1: " << endl; + Rectangle r1(10, 20); + r1.draw(); + r1.length(); + + cout << "r2: " << endl; + Rectangle r2(10.53, 20.25); + r2.draw(); + r2.length(); + + cout << "r3: " << endl; + Rectangle r3(10.2f, 20.2f); + r3.draw(); + r3.length(); + + return 0; +} \ No newline at end of file diff --git a/day7/d4.cpp b/day7/d4.cpp new file mode 100644 index 0000000..14cf2a9 --- /dev/null +++ b/day7/d4.cpp @@ -0,0 +1,55 @@ +// 类模版作为函数参数 +// 函数模版的参数可以是类模版 +#include +#include +#include + +using namespace std; + +// 类模版 +template +class Rectangle +{ +private: + T width, height; //矩形的宽和高 + +public: + Rectangle(T w, T h) : width(w), height(h) {} + +public: + void draw() + { + cout << "绘制矩形" + << "宽: " << width << "高: " << height << endl; + } + void length() + { + cout << "矩形周长: " << 2 * (width + height) << endl; + } +}; + +// 类模版作为函数参数 +// 将类模版作为函数参数,可以将类模版的数据类型泛化 +template +void drawShape(Rectangle &r) +{ + r.draw(); + r.length(); +} + +int main() +{ + cout << "r1: " << endl; + Rectangle r1(10, 20); + drawShape(r1); // 显式指定模版参数 + + cout << "r2: " << endl; + Rectangle r2(10.53, 20.25); + drawShape<>(r2); // 空<>表示自动推导 + + cout << "r3: " << endl; + Rectangle r3(10.2f, 20.2f); + drawShape(r3); // 表示自动推导 + + return 0; +} \ No newline at end of file diff --git a/day7/d5.cpp b/day7/d5.cpp new file mode 100644 index 0000000..acf3a20 --- /dev/null +++ b/day7/d5.cpp @@ -0,0 +1,46 @@ +// 类模版派生普通类 +#include +#include +#include + +using namespace std; + +template +class Shape +{ +protected: + T iPerimeter; + +public: + // virtual double area() = 0; + virtual T perimeter() { return iPerimeter; } // 周长 +}; + +class Rectangle : public Shape +{ +private: + int width, height; + +public: + Rectangle(int w, int h) : width(w), height(h) { iPerimeter = 2 * (w + h); } +}; + +class Triangle : public Shape +{ +private: + float a, b, c; + +public: + Triangle(float a, float b, float c) : a(a), b(b), c(c) { iPerimeter = a + b + c; } +}; + +int main() +{ + Rectangle r1(10, 20); + cout << "r1周长: " << r1.perimeter() << endl; + + Triangle t1(3.0f, 4.0f, 5.0f); + cout << "t1周长: " << t1.perimeter() << endl; + + return 0; +} diff --git a/day7/d6.cpp b/day7/d6.cpp new file mode 100644 index 0000000..25157fc --- /dev/null +++ b/day7/d6.cpp @@ -0,0 +1,37 @@ +// 类模版派生普通类 +#include +#include +#include + +using namespace std; + +template +class Shape +{ +public: + virtual T perimeter() = 0; // 周长 +}; + +// 类模版派生类模版 +// 派生的子类模版不能使用父类模版的成员变量,因为父类模版的成员变量是在编译时期确定的,而子类模版是在运行时期确定的 +template +class Rectangle : public Shape +{ +private: + T width, height; + +public: + Rectangle(T w, T h) : width(w), height(h) {} + virtual T perimeter() { return 2 * (width + height); } // 周长 +}; + +int main() +{ + // 必须使用 int 来指定类型 + Rectangle r1(10, 20); + cout << "r1周长: " << r1.perimeter() << endl; + + Rectangle r2(10.2f, 20.2f); + cout << "r2周长: " << r2.perimeter() << endl; + return 0; +} diff --git a/day7/d7.cpp b/day7/d7.cpp new file mode 100644 index 0000000..7682b8b --- /dev/null +++ b/day7/d7.cpp @@ -0,0 +1,47 @@ +// 类模版类内部实现 +// 在类模版内部的成员函数中,可以使用泛型成员变量 +#include +#include +#include +#include // sqrt + +using namespace std; + +template +class Point +{ +private: + T1 x; + T2 y; + +public: + Point(T1 x, T2 y) : x(x), y(y) {} + +public: + // ? T1, T2 是哪一个对象的泛型的具体化?是当前调用的对象的泛型 + // 此函数要求两个对象的泛型必须一致 + float distance(Point &other) + { + return sqrt((this->x - other.x) * (this->x - other.x) + (this->y - other.y) * (this->y - other.y)); + } +}; + +int main() +{ + // 类的泛型必须指定类型 + Point p1(2, 3); + Point p2(4, 5.5f); + cout << "p1和p2的距离: " << p1.distance(p2) << endl; + + Point p3(2, 3); + Point p4(4, 5.5f); + cout << "p3和p4的距离: " << p3.distance(p4) << endl; + + // 只有同类型的对象才能调用成员函数 + // 调用成员函数时,泛型的具体化是当前调用的对象的泛型 + Point p5(2, 3); + Point p6(4, 5.5f); + cout << "p5和p6的距离: " << p5.distance(p6) << endl; + + return 0; +} diff --git a/day7/d8.cpp b/day7/d8.cpp new file mode 100644 index 0000000..ab8aaf2 --- /dev/null +++ b/day7/d8.cpp @@ -0,0 +1,44 @@ +// 类模版类的外部实现 +// 类外部实现成员函数时,需要指定类泛型的类型 +// 再次声明泛型类型(转成函数模版) + +#include +#include +#include + +using namespace std; + +template +class Point +{ +private: + T x, y; + +public: + Point(T x, T y); + void show(); +}; + +template +Point::Point(T x, T y) : x(x), y(y) +{ +} + +template +void Point::show() +{ + cout << "x = " << x << ", y = " << y << endl; +} + +int main() +{ + cout << "p1: "; + Point p1(10, 20); + p1.show(); + + cout << "p2: "; + Point p2(10.2, 14.5); + p2.show(); + + return 0; +} diff --git a/day7/d9/MyPoint.h b/day7/d9/MyPoint.h new file mode 100644 index 0000000..30ec6a2 --- /dev/null +++ b/day7/d9/MyPoint.h @@ -0,0 +1,30 @@ +#ifndef __MYPOINT_H__ +#define __MYPOINT_H__ + +#include + +using namespace std; + +template +class Point +{ +private: + T x, y; + +public: + Point(T x, T y); + void show(); +}; + +template +Point::Point(T x, T y) : x(x), y(y) +{ +} + +template +void Point::show() +{ + cout << "x = " << x << ", y = " << y << endl; +} + +#endif // __MYPOINT_H__ \ No newline at end of file diff --git a/day7/d9/main.cpp b/day7/d9/main.cpp new file mode 100644 index 0000000..df501d4 --- /dev/null +++ b/day7/d9/main.cpp @@ -0,0 +1,14 @@ +#include "MyPoint.h" + +int main() +{ + cout << "p1: "; + Point p1(10, 20); + p1.show(); + + cout << "p2: "; + Point p2(10.2, 14.5); + p2.show(); + + return 0; +}