diff --git a/docs/CodingLanguage/CPP/Static&Extern.md b/docs/CodingLanguage/CPP/Static&Extern.md index 68351f2..f3491b8 100644 --- a/docs/CodingLanguage/CPP/Static&Extern.md +++ b/docs/CodingLanguage/CPP/Static&Extern.md @@ -1,10 +1,52 @@ # Static & Extern +!!! info ".h" + + + ## Static - 全局变量 限制在此文件内部 - 函数修饰 同上 -- 类中变量 所有类共享变量(注意需要在类的外部对这个变量进行定义) + +- 类中变量 所有类共享变量**(注意需要在类的外部对这个变量进行定义,也是对他进行初始化的地方)** +不能在初始化列表中初始化静态变量 + + +- 类中函数修饰 只能使用`static`变量,比如下面的例子中如果在foo函数中调用value就会报错 +这个函数是独立于对象之外的,没有隐含的`this`指针 + +??? example "code" + 注意12,18行的写法 + + ```c++ hl_lines="12 18 22 23 24" + #include + using namespace std; + + class A + { + public: + A() : value(0) { cout << "A() " << endl; }; + ~A() { cout << "~A" << endl; }; + static int count; + static void foo() + { + cout << "foo() " << count << endl; + } + + private: + int value; + }; + int A::count; + int main() + { + A a; + a.foo(); + A::foo(); + cout << a.count << endl; + cout << A::count << endl; + } + ``` ## Extern diff --git a/docs/CodingLanguage/CPP/TypeCast.md b/docs/CodingLanguage/CPP/TypeCast.md new file mode 100644 index 0000000..1159708 --- /dev/null +++ b/docs/CodingLanguage/CPP/TypeCast.md @@ -0,0 +1,40 @@ +# Type Cast + +!!! info + - **隐式类型转换** + - **显式类型转换** + - **整型提升** + - **无符号类型转换** + ![Alt text](https://zzh-pic-for-self.oss-cn-hangzhou.aliyuncs.com/img/202404261107274.png) + +## 强制类型转换 + +`cast-name(expression)` + +### static_cast + +> 只要不包含底层的const就可以使用 + +- `static_cast` 在相关的类型之间转换,比如 + - 一个父类和派生类之间的转换 + - `void * `到其他指针类型之间的转换 + - `int` `float`等类型之间的转换 +- 它的安全性比较高, + +```CPP +double m; +void *p = &m; +double *dp = static_cast(p); +``` + +### const_cast + +> 只能改变底层const +> + + + +### reinterpret_cast + +> 为转换对象的位模式提供更低层次的重新解释 +> diff --git a/docs/CodingLanguage/CPP/classes/Copy.md b/docs/CodingLanguage/CPP/classes/Copy.md index 7e5baa3..ba5dfae 100644 --- a/docs/CodingLanguage/CPP/classes/Copy.md +++ b/docs/CodingLanguage/CPP/classes/Copy.md @@ -1,5 +1,11 @@ # Copy Control +!!! info "Copy" + - 函数传参数 + ```c++ + + ``` + ```c++ class A { @@ -19,6 +25,14 @@ protected: ``` ## 拷贝构造函数 + +- 默认情况下,编译器会有一个 + - 原生类型值拷贝 + - class调用其拷贝函数 +- 但是对于指针而言,它也是值拷贝,导致有两个指针指向同一个元素。这导致它的管理不明确,可能对同一块地址进行两次甚至多次`delete`.这种情况下,要对析构函数、拷贝构造函数进行定义 +!!! success "Why const and why &" + - const: 不能改变 + - 引用: 不然传参数的时候发生值传递,又要调用拷贝函数,陷入死循环 ```c++ A(const A &rhs) : mi(rhs.mi) { @@ -26,10 +40,91 @@ A(const A &rhs) : mi(rhs.mi) } ``` +??? note "定义部分" + ```c++ + #include + using namespace std; + + class A + { + public: + A() : value(0) { cout << "A() " << endl; }; + A(int a) : value(a) { cout << "A(int a)" << endl; }; + A(const A &other) + { + this->value = other.value; + cout << "A(&)" << other.value << endl; + }; + + ~A() { cout << "~A" << endl; }; + + private: + int value; + }; + A f(int a) + { + cout << "f()" << endl; + return A(a); + } + A bar(A a) + { + cout << "bar" << endl; + return a; + } + ``` + +??? info "编译器优化问题" + ```c++ + int main() + { + + // 编译器优化 + // 拷贝构造被优化 相当于 xa = A(5) + A xa = f(5); + /* + f() + A(int a) + */ + + // 进行拷贝构造 + A xb = bar(xa); + /* + A(&)5 参数传入一次拷贝构造 + bar bar 调用 + A(&)5 拷贝构造 xb = 传回参数 + ~A 应该是那个参数被销毁了 + */ + A xc = A(11); + } + ``` + ![alt text](images/custom-image-1.png) ## 拷贝赋值运算 !!! note "拷贝" - 通常返回左值的引用 - - \ No newline at end of file + +## 效率问题 Vector + +> 由于vector运行过程中会发生扩容,所以拷贝构造会多次进行 +> + +!!! info "优化拷贝" + 将`alist.push_back(A(0));`改为`alist.emplace_back(0);`,可以不执行拷贝构造而是直接构造 + +C11 +禁用copy,`Person(const Person &rhs) = delete;` + + +```c++ +vector alist; +// push_back +alist.push_back(A(0)); +alist.push_back(A(1)); +alist.push_back(A(2)); + +alist.emplace_back(0); +alist.emplace_back(1); +alist.emplace_back(2); +``` diff --git a/docs/CodingLanguage/CPP/classes/OverloadOperator.md b/docs/CodingLanguage/CPP/classes/OverloadOperator.md new file mode 100644 index 0000000..9a91cce --- /dev/null +++ b/docs/CodingLanguage/CPP/classes/OverloadOperator.md @@ -0,0 +1,5 @@ +# Overload + +!!! info "info" + - +## \ No newline at end of file diff --git a/docs/CodingLanguage/CPP/test.cpp b/docs/CodingLanguage/CPP/test.cpp index ae89850..64789bf 100644 --- a/docs/CodingLanguage/CPP/test.cpp +++ b/docs/CodingLanguage/CPP/test.cpp @@ -4,57 +4,23 @@ using namespace std; class A { public: - A(int i) : mi(i) {} - A(const A &rhs) : mi(rhs.mi) + A() : value(0) { cout << "A() " << endl; }; + ~A() { cout << "~A" << endl; }; + static int count; + static void foo() { - cout << "A::A(&)" << endl; - } - A &operator=(const A &rhs) - { - mi = rhs.mi; - cout << "A::operator=()" << endl; - return *this; - } - virtual void f() - { - cout << "A::f(), " << mi << endl; - } - -protected: - int mi; -}; - -class B : public A -{ -public: - B(int i, int j) : A(i), mj(j) {} - void f() override - { - cout << "B::f(), " << mi << ", " << mj << endl; + cout << "foo() " << count << endl; } private: - int mj; + int value; }; - -class Base -{ -private: -public: - int a; - const int consA; - Base(int a) : Base(a, a) - { - cout << "Call Base(int a)" << endl; - } - Base(int m, int ConstM) : a(m), consA(ConstM) - { - cout << "Call Base(int m, int ConstM)" << endl; - } -}; - +int A::count; int main() { - Base m(55); - cout << m.a << " " << m.consA; + A a; + a.foo(); + A::foo(); + cout << a.count << endl; + cout << A::count << endl; } \ No newline at end of file diff --git a/docs/CodingLanguage/CPP/test.exe b/docs/CodingLanguage/CPP/test.exe index f73e93a..f630b22 100644 Binary files a/docs/CodingLanguage/CPP/test.exe and b/docs/CodingLanguage/CPP/test.exe differ diff --git a/docs/CodingLanguage/CPP/virtual.cpp b/docs/CodingLanguage/CPP/virtual.cpp new file mode 100644 index 0000000..cbb2f82 --- /dev/null +++ b/docs/CodingLanguage/CPP/virtual.cpp @@ -0,0 +1,95 @@ +#include +using namespace std; + +class A +{ +public: + A(int i) : mi(i) {} + A(const A &rhs) : mi(rhs.mi) + { + cout << "A::A(&)" << endl; + } + A &operator=(const A &rhs) + { + mi = rhs.mi; + cout << "A::operator=()" << endl; + return *this; + } + virtual void f() + { + cout << "virtual A::f(), " << mi << endl; + } + void g() + { + cout << "A::g()" << mi << endl; + } + +protected: + int mi; +}; + +class B : public A +{ +public: + B(int i, int j) : A(i), mj(j) {} + void f() override + { + cout << "B::f(), " << mi << ", " << mj << endl; + } + void B_single() + { + cout << "B::B_single()" << mi << "," << mj << endl; + } + void g() + { + cout << "B::g()" << mi << "," << endl; + } + +private: + int mj; +}; + +class Base +{ +private: +public: + int a; + const int consA; + Base(int a) : Base(a, a) + { + cout << "Call Base(int a)" << endl; + } + Base(int m, int ConstM) : a(m), consA(ConstM) + { + cout << "Call Base(int m, int ConstM)" << endl; + } +}; + +int main() +{ + + A *a = new A(1); + B *b = new B(2, 5); + a->f(); + b->f(); + /* + A::f(), 1 + B::f(), 2, 5 + */ + // a(1) + // 转换之后,调用, 虚函数仍然是原来的,这与vitual Table相关 + (static_cast(a))->f(); + (static_cast(a))->B_single(); + (static_cast(a))->g(); + /* + >> A::f(), 1 + >> B::B_single()1,0 + >> B::g()1 + */ + // b(2,5) + (static_cast(b))->f(); + // >> B::f(), 2, 5 + (static_cast(b))->g(); + // >> A::g() 2 + // (static_cast(b))->B_single(); +} \ No newline at end of file