cpp primer笔记110-面向对象程序设计

  1. 如果不想一个类被其他类继承,可以在定义的变量名后面加上final,这样如果其他类继承该类会报错。
class Base final
{virtual void func(){std::cout << "Base" << std::endl;}
};
/*class Son :public Base//报错
{
};*/
  1. override可以使得子类的函数不是虚函数的情况下重写父类的虚函数,而基类函数中的final可以使得子类无法重写。如果派生类的重写函数想要调用基类的函数,可以先写出基类的作用域再调用基类的函数,如果派生类对象想用基类而不是子类的同名函数,可以先写成基类的作用域运算符在调用基类函数。
    #define _CRT_SECURE_NO_WARNINGS 1
    #include<iostream>
    #include<map>
    class Base
    {
    public:virtual void func1(int) const{}virtual void func2(){}void func3() {};
    };
    class Son :public Base
    {
    public:void func1(int) const override//Son的func1和Base的func1匹配{Base::func1(1);}virtual void func2() final{}//void func2(int) override{} 错误,应该与Base类的形参列表匹配//void func3() override; 错误,基类中没有声明为func3的虚函数//void func4() override; 错误,基类中没有该函数
    };
    class cla :public Son
    {//void func2() 错误,无法重写基类的函数
    };
    int main()
    {Son s;s.Base::func1(1);return 0;
    }
    
  2. 派生类向基类转换的可访问性
    ![[Pasted image 20230925165218.png]]
	#define _CRT_SECURE_NO_WARNINGS 1#include<iostream>#include<map>#include<memory>class Father{};class SonA :public Father{void func(SonA& son){Father a = son;}friend void frifunc(SonA& son){Father a = son;}};class SonB :protected Father{void func(SonB& son){Father b = son;}friend void frifunc(SonB& son){Father b = son;}};class SonC :private Father{void func(SonC& son){Father c = son;}friend void frifunc(SonC& son){Father c = son;}};class GrandSonA :SonA{void func(GrandSonA& son){Father a = son;}};class GrandSonB :SonB{void func(GrandSonB& son){Father b = son;}};class GrandSonC:SonC{void func(GrandSonC& son){//Father c = son;不允许私有继承基类派生类的子类转换为基类}};int main(){std::unique_ptr<Father> faPtr1(new SonA());//std::unique_ptr<Father> faPtr2(new SonB()); //如果不在类内部,则不允许保护和私有继承的派生类转换为父类//std::unique_ptr<Father> faPtr3(new SonC());return 0;}
  1. 派生类友元不能访问基类的成员。struct默认继承保护级别是public继承,class继承默认保护级别是private继承
  2. 覆盖重载函数:
    #include <iostream>
    class base {
    public:virtual int func() {return 0;}virtual int func(int i) {return 1;}
    };class D1 : public base {
    public:int func() { return 2; }
    };class D2 : public D1 {
    public:int func(int i) { return 3;}
    };int main()
    {D1 d1;D2 d2;base *b1 = &d1;base *b2 = &d2;b1->func(1);b2->func();	return 0;
    }
    基类base中有重载函数func的两个版本,D1继承自base,覆盖了func()的版本,D2继承自D1,覆盖了func(int)的版本。
    • 主函数里使用动态绑定,base指针绑定D1对象,可以使用fun(int)版本,同样base指针绑定D2对象,也可以使用fun()版本。
    • 如果在D1调用func(int)版本,比如int funcc() {return func(1);},那么会编译报错,显示no
    • matching function for call to ‘D1::func(int)’。如果改成int funcc() {return func();}就没错了。同理,在D2中使用func()也会报错。
    • 如果直接用d1调用fun(int)版本,或者直接用d2调用func()版本,编译会报错。错误也是no matching function for call to ‘XXX’
    • 如果修改类D1和D2,把覆盖的虚函数去掉,如下所示:
    class D1 : public base {
    public://int func() { return 2; }
    };class D2 : public D1 {
    public://int func(int i) { return 3;}
    };
    • 派生类的作用域嵌套在基类的作用域之内。 D1只覆盖了无参版本的func函数,那么D1的作用域之内,func(int)版本的函数就被隐藏了。使用b1调用func(int)函数,编译器首先在D1作用域内找名字func,找到了名字func,就不会继续往外层作用域查找,此时参数不匹配,于是编译器报错。
    • 同样,D1中的funcc()函数调用func(int)函数,也是先从D1作用域开始查找名字func,也只能找到无参版本,找到无参版本后发现参数不匹配,于是报错。
    • 而如果使用动态绑定,即使用指针d1访问func(),查找名字将从静态类型的作用域开始,即从base的作用域开始查找,而base的作用域内两个版本的func都可见(其中无参版本的是被覆盖后的,有int参数的是原始的),所以找到名字func后还会进行参数匹配,不会出现编译错误。
    • 修改类D1和D2,把覆盖的虚函数去掉,那么D1和D2作用域内就没有名字func了,使用b1调用func(int)或者func()函数,都无法在D1作用域内找到函数名,于是在外层作用域中继续寻找,也就是在base作用域中查找,能找到重载的两个版本的函数,接着进行正常的函数匹配,也不会出现编译错误。
    • 而书上所说的using声明符,相当于将base作用域里的几个重载版本的函数都强行加到了里层的D1作用域里,也能解决2和3的问题。
    #define _CRT_SECURE_NO_WARNINGS 1
    #include <iostream>
    class base {
    public:virtual int func() { std::cout << 1 << std::endl; return 0; }virtual int func(int i) { return 1; }
    };class D1 : public base {
    public:using base::func;//如果使用using,则使用子类构造的父类使用父类的所有func函数重载,而不是子类int func() { return 2; }
    };class D2 : public D1 {
    public:using base::func;//如果添加using,则使用子类构造的父类使用父类所有func函数重载,而不是子类int func(int i) { return 3; }
    };int main()
    {D1 d1;D2 d2;base* b1 = &d1;base* b2 = &d2;D1().func();//这里使用子类的函数b1->func(1);b2->func();return 0;
    }
    
  3. 如果基类的指针通过派生类构造,如果基类的构造函数不是虚函数,则该指针的(派生类)对象会调用基类的析构函数,因此最好将基类的析构函数用virtual修饰,从而让该指针的对象调用派生类的析构函数。当然定义虚析构函数将不会有默认的移动操作,只能手动添加。
  4. 派生类中删除的拷贝控制与基类的关系
    ![[Pasted image 20230925232959.png]]

![[Pasted image 20230925233315.png]]

  1. 基类容器可通过指针来兼容派生类
    	#define _CRT_SECURE_NO_WARNINGS 1#include <iostream>#include <string>#include <memory>#include <deque>#include <algorithm>class Base{private:std::string str;int num;public:Base(const std::string& s = "No Word", int n = 0) :str(s), num(n) {};friend std::ostream& operator<<(std::ostream& os, const Base ba){os << ba.str << " " << ba.num;return os;}};class SonA :public Base{private:double val;public:SonA(const std::string& s = "No Word", int n = 0, double v = 0) :val(v), Base(s, n) {};friend std::ostream& operator<<(std::ostream& os, const SonA sonA){os << static_cast<const Base&> (sonA) << " " << sonA.val;return os;}};class SonB :public Base{private:char ch;public:SonB(const std::string& s = "No Word", int n = 0, char c = '\0') :ch(c), Base(s, n) {};friend std::ostream& operator<<(std::ostream& os, const SonB sonB){os << static_cast<const Base&> (sonB) << " " << sonB.ch;return os;}};class GrandSonA :public SonA{private:long lon;public:GrandSonA(const std::string& s = "No Word", int n = 0, double v = 0, long l = 0):lon(l), SonA(s, n, v) {};friend std::ostream& operator<<(std::ostream& os, const GrandSonA& grsonA){os << static_cast<const SonA&>(grsonA)<< " " << grsonA.lon;//可通过强制转换将派生类转换为基类来使用基类的函数return os;}};int main() {//std::vector<Base> vec1 = { Base("ewr",12),SonA("sdf",32,3) };//当派生类对象被赋值给基类对象时,其中的派生类部分被切掉//因此容器和存在继承关系的类型无法兼容std::deque<std::shared_ptr<Base>> vec2{ std::make_shared<Base>("sdf",234) };auto ba = std::back_inserter(vec2);auto fr = std::front_inserter(vec2);*ba = std::make_shared<SonA>("zfc", 123, 3.4);//注意,如果派生类继承方式为保护或者私有,则无法添加派生类构造的数据*fr = std::make_shared<SonB>("ergsdf", 10, '3');auto ins = std::inserter(vec2, vec2.begin());*ins = std::make_shared<GrandSonA>("zsdfs", 23, 234.234, 234234234);std::ostream_iterator<Base> os(std::cout, "\n");std::for_each(vec2.crbegin(), vec2.crend(), [&os](auto val) { os = *val; });//打印时,因为全部的是基类,所以每个对象只打印两个值,针对这种行为可以写一组虚函数例如下面的代码return 0;}
    #define _CRT_SECURE_NO_WARNINGS 1
    #include <iostream>
    #include <string>
    #include <memory>
    #include <deque>
    #include <algorithm>
    class Base
    {
    private:std::string str;int num;
    public:Base(const std::string& s = "No Word", int n = 0) :str(s), num(n) {};virtual std::ostream& SonOstream(std::ostream& os) const{os << this->str << " " << this->num;return os;}friend std::ostream& operator<<(std::ostream& os, const Base ba){return ba.SonOstream(os);}
    };
    class SonA :public Base
    {
    private:double val;
    public:SonA(const std::string& s = "No Word", int n = 0, double v = 0) :val(v), Base(s, n) {};virtual std::ostream& SonOstream(std::ostream& os) const{os << static_cast<const Base&> (SonA(*this)) << " " << this->val;return os;}friend std::ostream& operator<<(std::ostream& os, const SonA sonA){return sonA.SonOstream(os);}
    };
    class SonB :public Base
    {
    private:char ch;
    public:SonB(const std::string& s = "No Word", int n = 0, char c = '\0') :ch(c), Base(s, n) {};virtual std::ostream& SonOstream(std::ostream& os) const{os << static_cast<const Base&>(SonB(*this)) << " " << this->ch;return os;}friend std::ostream& operator<<(std::ostream& os, const SonB sonB){return sonB.SonOstream(os);}
    };
    class GrandSonA :public SonA
    {
    private:long lon;
    public:GrandSonA(const std::string& s = "No Word", int n = 0, double v = 0, long l = 0):lon(l), SonA(s, n, v) {};virtual std::ostream& SonOstream(std::ostream& os) const{os << static_cast<const SonA&>(GrandSonA(*this)) << " " << this->lon;return os;}friend std::ostream& operator<<(std::ostream& os, const GrandSonA& grsonA){//可通过强制转换将派生类转换为基类来使用基类的函数return grsonA.SonOstream(os);}
    };
    int main()
    {//std::vector<Base> vec1 = { Base("ewr",12),SonA("sdf",32,3) };//当派生类对象被赋值给基类对象时,其中的派生类部分被切掉//因此容器和存在继承关系的类型无法兼容std::deque<std::shared_ptr<Base>> vec2{ std::make_shared<Base>("sdf",234) };auto ba = std::back_inserter(vec2);auto fr = std::front_inserter(vec2);*ba = std::make_shared<SonA>("zfc", 123, 3.4);//注意,如果派生类继承方式为保护或者私有,则无法添加派生类构造的数据*fr = std::make_shared<SonB>("ergsdf", 10, '3');auto ins = std::inserter(vec2, vec2.begin());*ins = std::make_shared<GrandSonA>("zsdfs", 23, 234.234, 234234234);std::ostream_iterator<Base> os(std::cout, "\n");std::for_each(vec2.crbegin(), vec2.crend(), [](std::shared_ptr<Base> val) { val->SonOstream(std::cout); std::cout.put(10); });return 0;
    }
    
  2. 模板运行非类型参数传递。注:函数模板和类模板成员函数的定义通常放在头文件,而非模板函数把声明放在头文件,把定义放在源文件。一个类模板的每一个都形成一个独立的类,例如,类型Blob&ltstring&gtyu任何其他类型比如Blob&ltint&gt都没有任何关联,也不会对任何其他的Blob类型成员有特殊访问权限。
    #define _CRT_SECURE_NO_WARNINGS 1
    #include <iostream>
    #include <string>
    #include <memory>
    #include <deque>
    #include <algorithm>
    template<int N,int M,typename Type>
    bool swap(Type(&t1)[N], Type(&t2)[M])
    {if (N != M) return false;for (int i = 0; i < N; ++i){Type temp = t1[i];t1[i] = t2[i];t2[i] = temp;}return true;
    }
    int main() 
    {int num1[4]{ 3,4,5,2 }, num2[4]{ 8,7,6,5 };swap<4, 4>(num1, num2);//swap(num1, num2); 相当于上面的语句,如果上面的语句//中N和M都不等于对应的数组长度则或报错,如果是char数组,则需要将N和M加上一for (auto x : num1) std::cout << x << " ";std::cout << std::endl;for (auto y : num2) std::cout << y << " ";return 0;
    }
  3. 模板类内使用模板名不需要模板参数,但是模板类外使用模板名来定义类内的成员等操作则需要模板参数
    #define _CRT_SECURE_NO_WARNINGS 1
    #include <iostream>
    #include <string>
    #include <memory>
    #include <deque>
    #include <vector>
    #include <algorithm>
    template<class T> class BlobPtr
    {
    public:BlobPtr func1()//类内部不用写模板参数,只需要模板名{return BlobPtr();}BlobPtr func2();
    };
    template<class T>
    BlobPtr<T> BlobPtr<T>::func2()//类外部需要写模板参数和模板名
    {return BlobPtr<T>();
    }
    int main() 
    {return 0;
    }
    
  4. 友元类与类模板
    template <typename T> class C2 {
    // C2的每个实例和相同实例化的pal声明为友元
    friend class Pal<T>;
    //Pal2的所有实例都是C2的每个实例的友元
    template <typename x> friend class Pal2;
    //Pal3是一个非模板类,他是所有C2的友元。
    friend class Pal3;
    };
    
  5. 模板类型可以起别名
	#define _CRT_SECURE_NO_WARNINGS 1#include <iostream>#include <string>#include <memory>#include <deque>#include <vector>#include <algorithm>template<typename T> using partNo = std::pair<T, T>;template<typename T> using twin = std::pair<T, int>;int main() {partNo<int> intPair;//相当于pair<int,int>twin<std::string> strPair;//相当于pair<string,int>return 0;}
  1. 如果一个模板参数列表中从右往左有一串连续的模板参数可以通过编译器找到,则在实例化中可以省略指定被找到的模板参数。

    #define _CRT_SECURE_NO_WARNINGS 1
    #include <iostream>
    #include <string>
    #include <memory>
    #include <deque>
    #include <algorithm>
    template<typename T1,typename T2,typename T3>
    T1 sum(T2 num1, T3 num2)
    {return num1 + num2;
    }
    int main()
    {int a = 10;long b = 15;std::cout << sum<long>(a, b);//省略T2和T3return 0;
    }
    
  2. 针对部分需要解除const,引用,指针等修饰的类型cpp定义类标准类型转换模板。 ![[Pasted image 20230926214603.png]]

    #define _CRT_SECURE_NO_WARNINGS 1
    #include <iostream>
    #include <string>
    #include <memory>
    #include <deque>
    #include <algorithm>
    #include <type_traits>
    #include <vector>
    template<typename It>
    auto fcn2(It beg, It end) -> typename std::remove_reference<decltype(*beg)>::type//这里需要写typename,因为beg是通过It模板参数来转换
    {return *beg;
    }
    int main()
    {std::vector<int> vec = { 3,5,21,4 };std::cout << fcn2(vec.begin(), vec.end()) << std::endl;return 0;
    }
    
  3. 如果一个函数有多个重载则函数调用的模板类函数指针的时候,指针需要实例化模板参数

    #define _CRT_SECURE_NO_WARNINGS 1
    #include <iostream>
    #include <string>
    #include <memory>
    #include <deque>
    #include <algorithm>
    template<typename T>
    void swap(const T& t1, const T& t2)
    {
    }
    void func(void (*ptr)(const int&, const int&))
    {}
    void func(void (*ptr)(const double&, const double&))
    {}
    int main()
    {//func(swap);如果使用非实例化的函数,//编译器会因为不知道调用哪个func而报错func(swap<int>);return 0;
    }
    
  4. 针对函数传参时候的右值引用传递左值引用,引用折叠可以解决,X& &,X& &&和X&& &都折叠成类型X&,类型X&& &&折叠成X &&

    #define _CRT_SECURE_NO_WARNINGS 1
    #include <iostream>
    #include <string>
    #include <memory>
    #include <deque>
    #include <algorithm>
    template<typename T> void func1(T&){};
    template<typename T> void func2(const T&){};
    template<typename T> void func3(T&& val)
    {T t = val;//当传递一个右值调用Func3时,T是int//且通过拷贝val的值被初始化,当是一个左值时//T是int&
    };
    template<typename T>void func4(T&& val)
    {T t = val;//当val是一个左值,T则是一个左值引用t = [](T& t) {t *= t; return t; }(t);if (val == t)//t是val的一个引用,所以val永远等于t{std::cout << t << std::endl;}
    }
    int main()
    {int i = 10;const int ci = 20;func1(i);//i是一个int;模板参数类型T是intfunc1(ci);//ci是一个const int;模板参数T是const int//func1(5); 错误:传递给一个&参数的实参必须是左值func2(i);//i是一个int,模板T是一个intfunc2(ci);//ci是一个const int,但是模板参数T是intfunc2(5);//一个const &参数可以绑定一个右值;T是intfunc3(42);//实参是一个int类型的右值,模板参数T是int类型//当传递一个左值给func3的右值引用函数参数是,编译器会推断T为左值类型func3(i);//实参是一个左值,模板参数T是一个int&func3(ci);//实参是一个左值,模板参数T是一个const int&func4(i);return 0;
    }
    
    #define _CRT_SECURE_NO_WARNINGS 1
    #include <iostream>
    #include <string>
    #include <memory>
    #include <deque>
    #include <algorithm>
    template<typename F,typename T1,typename T2>
    void flip1(F f, T1 t1, T2 t2)
    {f(t2, t1);
    }
    template<typename F, typename T1, typename T2>
    void flip2(F f, T1&& t1, T2&& t2)
    //使用右值引用能够保证传入的右值和左值引用参数不会变成值类型
    {f(t2, t1);
    }
    template<typename F, typename T1, typename T2>
    void flip3(F f, T1&& t1, T2&& t2)
    {f(std::forward<T2>(t2), std::forward<T1>(t1));//forward能够将t1和t2的形参保持左值引用,右值引用,//const或者volatile修饰的情况下将将参数转发给函数//相当于针对左右值引用,值类型,const或者volatile之间的类型转换的static_cast,这里的转发t1和t2主要是将T2类型转发为实际对应类型从而在f函数中调用
    }
    void f(int v1, int& v2)
    {std::cout << v1 << " " << ++v2 << std::endl;
    }
    void g(int&& i, int& j)
    {std::cout << i << " " << j << std::endl;
    }
    int main()
    {int i = 5, j = 5;flip1(f, i, 10);f(10, j);std::cout << i << " " << j << std::endl;i = 5, j = 5;flip2(f, i, 10);f(10, j);std::cout << i << " " << j << std::endl;//flip2(g, i, 10);10是一个常量,传入过程中变为右值引用flip3(g, i, 10);std::cout << i << " " << j << std::endl;return 0;
    }
    
    10 6
    10 6
    5 6
    10 6
    10 6
    6 6
    10 6
    6 6
    
  5. 可变参数模板

    #define _CRT_SECURE_NO_WARNINGS 1
    #include <iostream>
    #include <string>
    #include <memory>
    #include <deque>
    #include <algorithm>
    #include <cstdarg>
    template<typename T,typename... Args>
    void func(const T& t, const Args&... rest)
    {std::cout << "Args大小 " << sizeof ...(Args) << std::endl;//可变参数模板参数大小std::cout << "rest大小 " << sizeof ...(rest) << std::endl;//可变参数模板参数大小
    }
    template<typename T>
    std::ostream& print(std::ostream& os,const T &t)
    {return os << t;
    }
    template<typename T,typename... Args>
    std::ostream& print(std::ostream& os, const T& t, const Args&... rest)
    {os << t << ", ";return print(os, rest...);
    }
    //print(cout,1,2,3,4,5);
    //print(cout,1,2,3,4);
    //print(cout,1,2,3);
    //print(cout,1,2);
    //print(cout,1)调用非可变参数版本的print
    int main()
    {const int i = 10;func(1, 2, 3, 4, 5, 6);func(2, 2.234, 0ull, "Sdfsdf", std::string("234"));print(std::cout, 1, 2, 3, 4, 5, 6);std::cout.put(10);print(std::cout, 2, 2.234, 0ul, "Sdfsdf", std::string("234"));return 0;
    }
    
  6. 模板类的成员函数显式具体化

    #define _CRT_SECURE_NO_WARNINGS 1
    #include <iostream>
    #include <string>
    #include <memory>
    #include <vector>
    #include <algorithm>
    template<typename T> class Foo
    {Foo(const T& t = T()) :mem(t) {};void Bar() { std::cout << 1 << std::endl; };T mem;
    };
    template < >
    void Foo<int>::Bar()
    {std::cout << 2 << std::endl;
    }
    int main()
    {return 0;
    }
    

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.hqwc.cn/news/126669.html

如若内容造成侵权/违法违规/事实不符,请联系编程知识网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

36.骑士周游算法及其基于贪心算法的优化

概述 骑士周游算法&#xff0c;叫做“马踏棋盘算法”或许更加直观。在国际象棋8x8的棋盘中&#xff0c;马也是走“日字”进行移动&#xff0c;相应的产生了一个问题&#xff1a;“如果要求马 在每个方格只能进入一次&#xff0c;走遍全部的64个方格需要如何行进&#xff1f;”…

【C语言】编译和链接

前言&#xff1a; 编译和链接是计算机程序开发中的两个重要步骤&#xff0c;用于将源代码转化为可执行的程序。 文章目录 一、翻译环境和运行环境二、翻译环境中的编译2.1 预处理&#xff08;预编译&#xff09;2.2 编译2.2.1 语法分析2.2.2 语法分析2.2.3 语义分析 2.3 汇编 三…

【RabbitMQ】初识消息队列 MQ,基于 Docker 部署 RabbitMQ,探索 RabbitMQ 基本使用,了解常见的消息类型

文章目录 前言一、初识消息队列 MQ1.1 同步通信1.2 异步通信1.3 MQ 常见框架及其对比 二、初识 RabbitMQ2.1 什么是 RabbitMQ2.2 RabbitMQ 的结构 三、基于 Docker 部署 RabbitMQ四、常见的消息类型五、示例&#xff1a;在 Java 代码中通过 RabbitMQ 发送消息5.1 消息发布者5.2…

吐血整理,最全Pytest自动化测试框架快速上手(超详细)

目录&#xff1a;导读 前言一、Python编程入门到精通二、接口自动化项目实战三、Web自动化项目实战四、App自动化项目实战五、一线大厂简历六、测试开发DevOps体系七、常用自动化测试工具八、JMeter性能测试九、总结&#xff08;尾部小惊喜&#xff09; 前言 pytest框架 pyte…

【深蓝学院】手写VIO第2章--IMU传感器--作业

这次作业坑很多&#xff0c;作业说明的不清楚&#xff0c;摸索了很长时间才将此次作业完成&#xff0c;在这里进行记录。 1. T1 1.1 题干 1.2 解答 1.2.1 法1&#xff0c;ros related方法 不知道为什么我的launch不了&#xff0c;在imu_utils目录下面建立build后&#xff0…

头部品牌停业整顿,鲜花电商的中场战事迎来拐点?

鲜花电商行业再次迎来标志性事件&#xff0c;曾经4年接连斩获6轮融资的明星品牌花加&#xff0c;正式宣布停业整顿。 梳理来看&#xff0c;2015年是鲜花电商赛道的发展爆发期&#xff0c;彼时花加等品牌相继成立&#xff0c;并掀起一波投资热潮&#xff0c;据媒体统计&#xf…

一座“城池”:泡泡玛特主题乐园背后,IP梦想照亮现实

“更适合中国宝宝体质”的主题乐园&#xff0c;被泡泡玛特造出来了。 9月26日&#xff0c;位于北京朝阳公园内的国内首个潮玩行业沉浸式 IP 主题乐园&#xff0c;也是泡泡玛特首个线下乐园——泡泡玛特城市乐园 POP LAND正式开园。 约4万平方米的空间中&#xff0c;泡泡玛特使…

C#学习系列相关之多线程(一)----常用多线程方法总结

一、多线程的用途 在介绍多线程的方法之前首先应当知道什么是多线程&#xff0c; 在一个进程内部可以执行多个任务&#xff0c;而这每一个任务我们就可以看成是一个线程。是程序使用CPU的基本单位。进程是拥有资源的基本单位&#xff0c; 线程是CPU调度的基本单位。多线程的作用…

VF11MR8M 冲销原因 小结

VF11&MR8M 冲销原因 小结 1.后台设置路径&#xff1a; SPRO->财务会计->总账会计->业务交易->调整过账/冲销->定义冲销原因 反记账&#xff1a; 2.前台操作使用01–当前期间回转 不会反记账&#xff0c;冲销凭证 过账日期 按 原凭证过账日期&#xff0…

学习记忆——数学篇——算术——无理数

谐音记忆法 2 \sqrt{2} 2 ​≈1.41421&#xff1a;意思意思而已&#xff1b;意思意思&#xff1b; 3 \sqrt{3} 3 ​≈1.7320&#xff1a;—起生鹅蛋&#xff1b;一起生儿&#xff1b; 5 \sqrt{5} 5 ​≈2.2360679&#xff1a;两鹅生六蛋(送)六妻舅&#xff1b;儿儿生&#xf…

数据结构-----平衡二叉树

目录 前言 1.平衡二叉树 1.1概念与特点 1.2与二叉排序树比较 1.3判断平衡二叉树 2.平衡二叉树的构建 2.1平衡因子 BF 2.2 LL型失衡&#xff08;右旋&#xff09; 2.3 RR型失衡&#xff08;左旋&#xff09; 2.4 LR型失衡&#xff08;先左旋再右旋&#xff09; 2.5 RL…

Next.js 入门笔记

前言 之前初步体验了 React 的魅力, 又看文档理解了一下 useState 和 useEffect, 目前初步理解的概念是: useState 用来声明在组件中使用并且需要修改的变量 useEffect 用来对 useState 声明的变量进行初始化赋值 可能理解的不太准确, 不过大概差不多是这么个意思. 但是再往后…