C++primer总结

2023-11-09

目录

第一章      数据处理... 2

整形...2

第二章      复合类型... 3

数组...3

字符串...4

枚举...5

指针...5

第三章      函数的使用... 6

内联函数...6

默认参数...6

函数的重载...7

函数的模板...7

第四章      内存模型和名称空间... 7

文件的单独存放...7

变量的链接性...7

函数的链接性...8

语言的链接性...10

动态开辟...10

命名空间...10

命名空间的运用实例...12

第五章      类的使用... 13

规范写类...13

第六章      类和动态内存分配... 15

类中的静态成员...15

构造1,构造2,析构2,析构2.17

隐式成员函数...17

new创建的用delete,但是new []创建的用delete []18

静态成员函数由于只是和类相关,所以也只能调用静态成员变量。...18

第七章      类的继承... 21

默认参数...21

第八章      重用代码... 22

多重继承...22

模板的使用...24

第九章      友元异常和其他... 27

友元类...27

第十章      string类和标准模板库... 28

string类...28

智能指针...28

联合容器...30

第十一章      输入输出和文件... 31

 

第一章         数据处理

整形

整形:short(16)、int(16-32)、 long(32) 头文件limits包含范围

#include<iostream>

using namespace std;

void main()

{

int int_max = INT16_MAX;

short short_max = SHRT_MAX;

    long long_max = LLONG_MAX;

    cout<< sizeof short_max <<"\t"<<sizeof(int)<<"\t"<<sizeof long_max<< endl;

}

数据可以大一点就使用unsigned long long

C++用三种基数来表示整数,10,8,16,当然也可以在数字后面加上LU来说明是long和unsigned

#include<iostream>

/*

* they are same

*/

using namespace std;

void main()

{

int ten = 42;

    int eight = 052;

    int sixteen = 0x2A;

    cout<< ten << "\t" << eight<< "\t" << sixteen << endl;

}

字符型

字符型char

Unsigned char 和signedchar 可以让char的值从0-255

Float32位  double64  记数可以使用科学计数法3.2E2=320

 

 

 

第二章         复合类型

数组

字符串以’\0’结尾,是字符串类型就发生了取得内存地址的条件,此外char str[6];中

Str=&str[0];所以不可以字符串之间赋值

#include<iostream>

//#include<cstring>

/*

* 字符串赋值的方法有两种(常用),直接赋值,从键盘输入

*在数组中 str[6], str=&str[0];

*/

using namespace std;

void main()

{

    char str1[6] = { 'h','e','l','l','o' };// it is char array

    char str2[6] = { 'h','e','l','l','o' ,'\0'};//it is string

    char str3[6] = "hello";                   //autoto add \0,it is string

    char str4[] = "hello";                    //it isstring

    cout<< "hello""everyone" << endl;//allow to jointstring

}

 

 

#include<iostream>

//#include<cstring>

/*

* char[] 以/0结尾,所以在键盘进行输入时有了空格,则以为结束,可以使用cin.getline(city,len),cin.get(city,len)输入。

*getline()是达到len长度时候结束,或者遇到换行的时候结束。但是get()遇到换行结束,但是可接受换行。

*

*/

using namespace std;

void main()

{

    char city[20];

    char name[20];

    //cin.getline(city,20);cin.getline(name,20);与下一行等效

    cin.get(city,20); cin.get(); cin.get(name, 20);

    cout<< name<<"\t"<<city<< endl;

}

#include<iostream>

//#include<cstring>

/*strcpy(str1,str2)   strcat(str1,str2)

* char[] 以/0结尾,所以在键盘进行输入时有了空格,则以为结束,可以使用cin.getline(city,len),cin.get(city,len)输入。

*getline()是达到len长度时候结束,或者遇到换行的时候结束。但是get()遇到换行结束,但是可接受换行。

*

*/

using namespace std;

void main()

{

    char city[20];

    char name[20];

    //cin.getline(city,20);cin.getline(name,20);与下一行等效

    cin.get(city,20); cin.get(); cin.get(name, 20);

    cout<< name<<"\t"<<city<< endl;

}

 

 

字符串:

#include<iostream>

#include<string>

/*

*字符串相当于字符数组,可以和字符数组一样使用

*字符串可以直接赋值,相加,拼接,可以直接cin和cout

*/

using namespace std;

void main()

{

    string str1 = "nihao";

    if (str1[5] =='\0') { cout <<"hello everyone\n"; }

    string str2 = str1 + " zxw\n";

    cout<< str2<<str2.length()<<"\t"<<str2.size();

}

结构体和共用体的使用

结构体是可以定义多个数据类型,但是共用体是每次只能储存一个值

#include<iostream>

#include<string>

/*

*/

using namespace std;

struct  mystruct

{

    string name;

    int studentno;

    char sex;

    bool good : 1;

    union id

    {

        float salary;

        string career;

    }x;

}my1;

void main()

{

   

    my1.x.salary= 100;

 

}

枚举:

只是定义了赋值操作,没有运算操作,当然,赋值附很大的时候将会发出警告,按照原则,应该有多少赋值多少

#include<iostream>

#include<string>

/*

*/

using namespace std;

void main()

{

    enum  my{ONE=1,TWO=2,THREE};

    cout<< THREE << endl;

}

指针:

在c++创建的时候,计算机分配用来储存地址的内存,并不会去储存值,所以为数据提供空间是一个独立的步骤。指针的加减是以所在的类型为单位个数进行加减。*(a+1)=a[1];

创建动态数组:

#include<iostream>

#include<string>

/*

当内存耗尽时候new将会返回0,delete释放内存,并不会删除指针

 

*/

using namespace std;

void main()

{

    int* p_int = new int;

    *p_int= 1024;

    delete p_int;

    //delete p_int;不能再次调用释放内存的delete,会发生我发预料的事情

    float * P_float;

    float ft = 2.1;

    P_float= &ft;

    //delete P_float;不能释放栈里面的内存,只能释放堆得

}

C++对数据有三种处理的方式自动存储,随着函数产生随着函数消亡,静态存储,生命周期可能是整个程序的生命周期,动态存储由程序员控制。

 

 

 

第三章         函数的使用

内联函数:example:

inline void Swap(floata, float b)

{

    a = a + b;

    b = a - b;

    a = a - b;

}

不能递归调用,原理是,所有的代码翻译成机器代码进行解读,正常的函数调用需要机器跳到指定的位置,但是内联函数就不需要了,把代码镶嵌在内部,但是后果是占用的内存较多。

引用变量:

引用的变量建立就直接赋值;

传递参数的三种方式:值传递,指针传递和引用传递,引用实质上是内存中同一个地址的别名,对于引用,会发生值的改变,除非将值设置成const的引用的类型。小的值传递通常使用值传递,大一点的比如结构体这些使用指针,对象则使用引用传递,仅是建议。

 

默认参数

默认参数从右往左开始赋值,这样的方式仅仅是提供了一种便捷的操作方式而已。

void Swap(floata, float b=9)

{

    a = a + b;

    b = a - b;

    a = a - b;

}

 

函数的重载:

参数的数目和类型的不相同可以重载函数,建议少用。

 

函数的模板:

template<classany> void Swap(any &q1,any &q2);//定义模板函数,在调用的时候叫做模板的实例化

template void Swap<int>(int &q1,int &q2);//模板显示具体化

 

 

 

第四章         内存模型和名称空间

文件的单独存放:

一般可以分为三种文件:头文件(负责各种声明和全局变量或者define的定义等),结构文件(为头文件的函数等定义的文件),调用文件(包含main的文件)

头文件的包含一般使用“”,使用<>会从标准库里面先去寻找。

 

储存的持续性,作用域和链接性:

自动储存持续性:在函数内部定义的局部变量(作用域是由一个花括号括起来的东西)

静态存储持续性:在函数外部定义或者static定义的变量,作用域由全局和局部。

动态存储持续性:由程序员指定new创建直到delete删除。存活周期结束。

注:在函数内部声明的static 和new 创建的东西虽然存在,但是由于作用域的存在,在别的地方不好引用。

 

变量的链接性:

(在另一个源文件定义)在函数外部定义,则全局变量,链接性为外部,即所有文件可以使用,但是加上extern声明存在之后可以使用。但是变量的定义的时候附加static 或者 const则在本文件可以使用,链接性为内部。

(在头文件里面定义的变量,建议不要再这里面定义)包含头文件,则包含里面的所有定义了,如果不声明为内部链接性,在多个文件使用这个头文件时候,将会发生重复定义错误。不能定义外部链接性的变量。

Example:(三个文件)

#pragma once

//mytemp1.h

#ifndef zylg1_

#define zylg1_

template<classany> void Swap(any &q1,any &q2);//定义模板函数,在调用的时候叫做模板的实例化

template void Swap<int>(int &q1,int &q2);//模板显示具体化

const int b = 8;

static int a = 6;

#endif // !zylg1_

 

//metemp1.cpp

#include<iostream>

#include"mytemp1.h"

std::string extern1 = "具有外部链接性的变量,可以在全部文件使用,加上extern说明就行";

static std::string str1 ="声明为静态的具有内部链接性,只可以在本文件使用";

const std::string str2 ="声明为静态的具有内部链接性,只可以在本文件使用";

template<classany> void Swap(any &q1,any &q2)

{

    q1 = q1 + q2;

    q2 = q1 - q2;

    q1 = q1 - q2;

}

 

//temp.cpp包含main()文件

#include<iostream>

#include"mytemp1.h"

#include<string>

using namespace std;

extern string extern1;//使用另外一个源文件定义的

void main()

{

    extern1= "这是重新使用外部变量";

    int a1 = 2, a2 = 4;

    Swap(a1,a2);

    cout<< a1 << a2 << endl;

    cout<< extern1<<b<<endl;

 

}

 

函数的链接性:

(在另一个源文件)同样的如果不添加static或者const的函数,则是外部链接性的。但是内部链接性声明之后,那就意味着在别的源文件里面重新定义函数不会发生重复定义的错误。

//metemp1.cpp

#include<iostream>

void Swap(int &a,int &b)

{

    a = a + b;

    b = a - b;

    a = a - b;

}

//temp.cpp包含main()文件

#include<iostream>

#include<string>

using namespace std;

extern  void Swap(int &q1,int &q2);

void main()

{

    int a1 = 2, a2 = 4;

    Swap(a1,a2);

    cout<< a1 << a2 << endl;

 

}

 

//metemp1.cpp

#include<iostream>

static void Swap(int &a,int &b)

{

    a = a + b;

    b = a - b;

    a = a - b;

}

 

//temp.cpp包含main()文件

#include<iostream>

#include<string>

using namespace std;

void Swap(int &q1,int &q2)

{

    q1 = q1 + q2;

    q2 = q1 - q2;

    q1 = q1 - q2;

}

void main()

{

    int a1 = 2, a2 = 4;

    Swap(a1,a2);

    cout<< a1 << a2 << endl;

 

}

注:extern只是让阅读代码的人知道外部存在这东西,并没无多大作用,可省略,但不建议。这也就是头文件的由来,可以看成是全部的外部的成员集合在一起,但是省略了extern。

 

语言的链接性:

由于c和c++编译器处理的效果不一样,

//temp.cpp包含main()文件

#include<iostream>

#include<string>

using namespace std;

extern "C++" void Swap(int &q1,int &q2);

void main()

{

    int a1 = 2, a2 = 4;

    Swap(a1,a2);

    cout<< a1 << a2 << endl;

 

}

 

动态开辟:

C++的内存分成三个部分静态变量,自动变量,和动态储存部分,new负责在heap里面找到合适的内存。New的用法

//temp.cpp包含main()文件

#include<iostream>

#include<string>

using namespace std;

struct student

{

    char name[20];

    int num;

};

void main()

{

    char ch1[30], ch2[30];

    student *st1, *st2;

    int *num1, *num2;

    st1= new student;//place create in heap

    st2= new (ch1) student;//place create in ch1

    num1= new int;//place create in heap

    num2= new (ch2) int;//create in ch2

    cout<< st1 << "\t" << st2<< "\t" << &ch1 << endl;

    cout<< num1 << "\t" << num2<< "\t" << &ch2 << endl;

}

 

命名空间:

//temp.cpp包含main()文件

#include<iostream>

#include<string>

/*

*不允许在函数内部命名名称空间

*名称空间可以嵌套

*当名称空间的名称省略的时候就相当于具有内部链接性的静态全局变量。是一种好的替代方式。

*名称空间的using声明(使用单个)和using 编译(使用全部)

*/

namespace myspace

{

    using std::string;//using声明

    using std::cout;

    using std::cin;

    string name;

    int num;

    void show()

    {

        cout<< name << "\t" << num<<std::endl;

    }

    void input()

    {

        cin>> name >> num;

        show();

    }

 

}

namespace myspace//和上一个空间是同一个空间,未写完继续写

{

    string str = "你好啊,我在myspace空间里面";

    namespace myspaceson //可以进行嵌套,命名空间就相当于一个作用域。

    {

        string str = "hello every one";

    }

}

namespace my =myspace;//别名

void main()

{

    using namespace myspace;//using 编译

    input();

    cout<< myspaceson::str << std::endl;

}

命名空间的运用实例

#pragma once

//mytemp1.h

#ifndef zylg1_

#define zylg1_

namespacemyspace1

{

    namespace//==static or constdefine

    {

        int number = 30;

    }

    void Swap(int &a,int &b);

}

namespacemyspace2

{

    void Show(inta,int b);

}

#endif // !zylg1_

 

//metemp1.cpp

#include<iostream>

#include"mytemp1.h"

namespacemyspace1

{

    void Swap(int &a,int &b)

    {

        a = a + b; b =a - b; a = a - b;

    }

}

namespacemyspace2

{

    using namespace std;

    void Show(inta,int b)

    {

        cout<< "a=" << a << "\t b=" <<b << endl;

    }

}

//temp.cpp包含main()文件

#include<iostream>

#include "mytemp1.h"

 

void main()

{

    int a=2,b=4;

    using namespace myspace1;//using 编译

    Swap(a,b);

    myspace2::Show(a,b);

   

}

 

 

 

第五章         类的使用

规范写类

#pragma once

//mytemp1.h

#ifndef zylg1_

#define zylg1_

namespacemyspace1

{

    class Time

    {

    private:

        int hours, minutes;

    public:

        Time(int,int);

        Time();

        void addMin(intm);

        void addHor(inth);

        void Reset();

        Time operator+(const Time& t)const;

        void Show()const;//对于不修改里面的值得函数,应该在后面加上const,防止数据修改

friend void display(constTime &t);

friend std::ostream&operator<<(std::ostream &os,const Time &t);

    };

}

#endif // !zylg1_

 

//metemp1.cpp

#include<iostream>

#include"mytemp1.h"

namespacemyspace1

{

    namespace

    {

        using std::cout;

        using std::endl;

    }

    Time::Time()

    {

 

    }

    Time::Time(inth=0,int m=0)

    {

        if (m >= 60)

        {

            hours= m / 60+h;

            minutes= m % 60;

        }

        else

        {

            hours= h;

            minutes= m;

        }

    }

    void Time::addMin(int m)

    {

        hours+= (m + minutes) / 60;

        minutes= (m + minutes) % 60;

    }

    void Time::addHor(int h)

    {

        hours+= h;

    }

    void Time::Reset()

    {

        hours= minutes = 0;

    }

    Time Time::operator+(constTime& t)const

    {

        return Time(hours + t.hours, minutes + t.minutes);

    }

    void Time::Show()const

    {

        cout<< hours << ":" << minutes<< endl;

    }

void display(constTime &t)

    {

        cout<< t.hours << ":"<< t.minutes << endl;

    }

std::ostream& operator<<(std::ostream & os, const Time &t)

    {

        cout<< t.hours << ":"<< t.minutes << endl;

        return os;

    }

}

//temp.cpp包含main()文件

#include<iostream>

#include "mytemp1.h"

/*

*规范的格式,在头文件不许出现外部链接性的全局变量,在源文件尽量不出现,此外命名空间用起来,好了万事大吉

*/

void main()

{  

    using myspace1::Time;

    Time t1(1,31),t2(2,30),t3,t4;

    t3= t1 + t2;

    t1.Show();

    t2.Show();

    t3.Show();

    t4= t1 + t2 + t3;//t1.operator+(t2.operator+(t3))

    t4.Show();

display(t4);//it is friendfuntion

}

Cout<<返回的时ostream的对象,所以可以继续<<

 

 

 

第六章         类和动态内存分配

:(类的声明只是描述内存的分配,但是不会分配内存)

类中的静态成员不能够直接初始化,其余可以,但是const int/枚举 类型的静态成员可以初始化。静态成员赋值那就意味该静态变在内存中存在,那就得分配内存(类的声明只是描述内存的分配),所以如例题中:在类中定义staticc int num_strings ;

然后初始化   int  StringBad::num_strings = 3;这就相当于申请了一个int大小的内存去储存静态变量。

    class StringBad

    {

    private:

        char * str="shixsa";//可以赋值,但是意义不大。

        int len=3;

    public:

        //static const std::stringnum_strings="hello";//can`t not to initialize

        static const int num_strings = 2;//can initialize

    public:

        StringBad(const char *s);

        StringBad();

        ~StringBad();

        friend std::ostream &operator<<(std::ostream &os,const StringBad &st);

    }

 

静态变量的使用

#pragma once

//mytemp1.h

#ifndef zylg1_

#define zylg1_

namespace myspace

{

 

    namespace

    {

        using std::cout;

        using std::cin;

        using std::endl;

    }

    class StringBad

    {

    private:

        char * str="shixsa";

        int len=3;

    public:

        static  int num_strings;

        void display();

        StringBad(const char *s);

        StringBad();

        //~StringBad();

        friend std::ostream &operator<<(std::ostream &os,const StringBad &st);

    };

}

 

#endif // !zylg1_

 

//metemp1.cpp

#include<iostream>

#include"mytemp1.h"

namespace myspace

{

    int  StringBad::num_strings = 3;

    void StringBad::display()

    {

 

 

        cout<< StringBad::num_strings << endl;

    }

    StringBad::StringBad()

    {

        StringBad::num_strings++;

    }

}

//temp.cpp包含main()文件

#include<iostream>

#include"mytemp1.h"

void main()

{

    using myspace::StringBad;

    StringBad st;

    st.display();

    StringBad st1;

    st1.display();

    StringBad st2;

    st2.display();

    StringBad st3;

    st3.display();

 

}

构造1,构造2,析构2,析构2

隐式成员函数

1) 默认构造函数 classname::classname(){}

2) 复制构造函数 classname::classname(const classname& cla){}

    StringBad st;

    StringBad st1(st);

    StringBad st2=StringBad(st);

    StringBad st3=st;

StringBad* st4 = new StringBad(st);

在赋值进行操作时,出现指针或者其他因素时最好显示定义,不然两个指针指向同一地址,一旦释放,就不好了

3) 赋值操作符=

4) 默认析构函数classname::~classname()

5) 地址操作符&

 

new创建的用delete,但是new []创建的用delete []

静态成员函数由于只是和类相关,所以也只能调用静态成员变量。

 //zylgstring.h

#pragma once

#include<iostream>

#ifndefZYLG_STRING

#define ZYLG_STRING

usingstd::cin;

usingstd::cout;

using std::ostream;

using std::istream;

namespaceZYLGSPACE

{

   

    class String

    {

    private:

        char *str;

        int len;

        static int num_strings;

        static const int CINLIMIT = 100;

    public:

        //constrators and other methods

        String(const String &s);//复制构造函数

        String();

        String(const char *s);

        ~String();//析构函数

        int length()const {return len; }

        //overloaded operator methods,()=[]->这四个符号只能在类的成员函数里面进行重载

        String & operator=(const String& s);

        String & operator=(const char*s);

        char & operator[](int i);

        const char & operator[](inti)const;

        //friend function

        friend bool operator>(constString& s1, const String &s2);

        friend bool operator<(constString& s1, const String &s2);

        friend bool operator==(constString& s1, const String &s2);

        friend std::ostream &operator<<(std::ostream &os, const String &s);

        friend std::istream &operator>>(std::istream &isString &s);

        //static function

        static int HowMany();

    };

}

#endif // !ZYLG_STRING

 

//zylgstring.cpp

#include<cstring>

#include"zylgstring.h"

#pragma warning(disable:4996)

namespaceZYLGSPACE

{

    int String::num_strings = 0;

    int String::HowMany()

    {

        return num_strings;

    }

    String::String(constchar* s)

    {

        len= std:: strlen(s);

        str= new char[len + 1];

        //std::strcpy(str, s);

        num_strings++;

 

    }

    String::String()

    {

        len= 4;

        str= new char[1];

        str[0]= '\0';

        num_strings++;

    }

    String::String(constString& s)

    {

        num_strings++;

        len= s.len;

        str= new char[len + 1];

        //std::strcpy(str, s.str);

    }

    String::~String()

    {

        --num_strings;

        delete[] str;

    }

    String & String::operator=(constString& st)

    {

        if (this == &st) {return *this; }

        delete[] str;

        len= st.len;

        str= new char(len + 1);

        //std::strcpy(str, st.str);

        return *this;

    }

    String & String::operator=(constchar* s)

    {

        delete[] str;

        len= std::strlen(s);

        str= new char(len + 1);

        std::strcpy(str,s);

        return *this;

    }

    char & String::operator[](inti)

    {

        return str[i];

    }

    const char & String::operator[](inti)const

    {

        return str[i];

    }

    bool operator<(const String& s1,constString& s2)

    {

        return (std::strcmp(s1.str,s2.str)<0);

    }

    bool operator==(const String& s1, constString& s2)

    {

        return (std::strcmp(s1.str,s2.str)==0);

    }

    bool operator>(const String& s1, constString& s2)

    {

        return s2.str < s1.str;

    }

    ostream & operator<<(ostream & os, const String&st)

    {

        os << st.str;

        return os;

    }

 

    istream & operator >> (std::istream & is, String &s)

    {

        char temp[String::CINLIMIT];

        is.get(temp, String::CINLIMIT);

        if (is)

        {

            s = temp;

        }

        while (is &&is.get() != '\n')

        {

            continue;

        }

        return is;

    }

 

 

}

 

 

 

第七章         类的继承

默认参数构成的构造函数,在全部是默认参数时,直接定义对象就行,不用加括号,如下

tabletennisplayer(const char * first="none",constchar * last="none",bool has=false);//exist default

tabletennisplayer::tabletennisplayer(constchar * first, const char * last ,bool has ){}

tabletennisplayer t1("buxnasox"),t2;

成员初始化列表只能用于构造函数,而且:之后的数只能是构造函数或者成员变量,调用时先调用基类的构造函数再调用子类的构造函数。析构函数则是先子类再基类。

2.论继承:继承有公有,私有和保护继承,保护继承是子类能访问,但是其他类不能访问,在基类的成员变量和成员函数如果私有的,那就得通过基类的公有或者保护函数来访问。

子类可以在基类的基础上添加属性,但是不能删除属性。

构造函数,析构函数,友元函数不能继承,当然赋值=也不能继承

3.虚函数的理解:虚函数的存在可以使用动态连编(在运行时选择正确的虚方法的代码),虚函数的实现的方式是,在类中存在虚方法时,类就会自动增加一个一种数组(虚函数表)vtal,里面存放了类对象声明的虚函数的地址。那就形成了每一个函调用时都额外增加了到该表中寻找地址的操作。当然虚函数,也只有成员函数和析构函数可以成为。

Class A;

Class B:publicA

A *a,a1;

B b;

a=&a1;a->display();

a=&b;a->display();

在基类声明display()为虚函数

虚基类是 “虚函数=0;”

 

 

 

第八章         重用代码

多重继承:

 

多重继承最好有虚基类,排除二义性,再者就是,进行子类构造的时候,并不能进行虚基类的构造,因为数据不能从子类传递到虚基类的基类。如果一个派生类有多个派生基类,而多个派生基类又有共同基类,则会在该派生类里面保存共同基类的数据成员的多份同名成员。在引用这些同名成员的时候必须加上直接基类的限定符。

class A

{

   

public:

    int n;

    void fun();

};

class B :public A

{

public:

    int data_b;

};

class C :public A

{

public:

    int data_c;

};

class D :public B,public C

{

public:

    int data_d;

   

};

 

    D d1;

    d1.B::fun();//正确的使用成员数据的方式

    d1.C::fun();

注意:子类只能直接调用直接基类的东西

但是使用虚拟继承,那样只会在D类里面只有一个间接基类的成员,但是由于构造函数不能从子类传递数据到虚拟继承的派生类,所以构造函数必须全部重新构造完全

//temp.cpp包含main()文件

#include<iostream>

#include"work.h"

class A

{

   

public:

    A(int n):n(n){}

    int n;

    void fun();

};

class B :virtual public A

{

public:

    B(int n) :A(n) {}

    int data_b;

};

class C :virtual public A

{

public:

    C(int n) :A(n) {}

    int data_c;

};

class D :public B,public C

{

public:

    D(int n) :A(n), B(n), C(n) {}//如果不是虚拟继承将会发生错误

    int data_d;

   

};

void main()

{

    //using  namespacezylgclassextend;

    using namespace WORKSPACE;

   

    D d1(1);

    d1.fun();

}

模板的使用:

//stack.h

#pragma once

#ifndefSTACK_H_

#define STACK_H_

namespaceSTACKSPACE

{

    template <classType>

    class Stack

    {

    private:

        enum { MAX = 10 };

        int top;

        Type items[MAX];

    public:

        Stack();

        bool isfull()const;

        bool isempty()const;

        bool push(constType& item);

        bool pop(Type &item);

    };

    template <classType>

    Stack<Type>::Stack():top(0) {}

 

    template <classType>

    bool Stack<Type>::isempty()const {return top == 0; }

 

    template <classType>

    bool Stack <Type>::isfull()const {return (top+1) == MAX; };

 

    template <classType>

    bool Stack<Type>::push(constType& item)

    {

        if (top < MAX)

        {

            items[top++]= item;

            return true;

        }

        else return false;

    }

 

    template <classType>

    bool Stack<Type>::pop(Type&item)

    {

        if (top > 0)

        {

            item = items[--top];

            return true;

        }

        else

        {

            return false;

        }

    }

}

#endif // !STACK_H_

 

template <class T,int n>

    classclassname

    {

    public:

        voidshow();

    };

template <class T,int n>

void classname<T, n>::show() {}

 

template <classT1,class T2>

    class classname

    {

    public:

        void show();

    };

       template<class T1,class T2>

    void classname<T1, T2>::show() {}

 

 

可以在模板里面加入模板,也可以模板函数当然有内部类的说法,可以定义内部类,类定义得简单一些就使用内部类吧。

内部类

内部类与外部类的关系

       内部类和外部类是什么关系了,事实上他们什么关系也不是,既不是朋友,也不是父子关系,外部类对内部类没有特权, 内部类对外部类也没有特权, 他们的关系,跟内部类定义在外部类外面一样。

 

内部类的使用方法

       如果要在调用内部类函数,可以主要使用:

    

[cpp] view plain copy

1.  A::InClass a;  

2.  a.funcB();  

 

内部类的作用

     1)内部类主要是为了避免命名冲突;(内部类定义为public) 

     2)为了隐藏名称(内部类定义为private/protected)

 

class A

{

    class B

    {

    public:

        void display() {std::cout<< "你好\n"; }

    };

    B b1;

public:

    void show() {b1.display(); std::cout<< "hello\n"; }

};

 

内部模板的使用

template <classT1,class T2>

    class classname

    {

    public:

        template<classU>

        class innerclass//内部模板

        {

            U u1;

            public:

                void display(Uu1, T1 t);

        };

        innerclass<int> in1;

        template<classY>//模板函数

        void prin(Ystr);

        void show();

    };

    template <classT1,class T2>

    void classname<T1, T2>::show() {}

   

    template<classT1,class T2>

    template<classU>

    void classname<T1, T2>::innerclass<U>::display(Uu1,T1 t) { cout << u1 + t << endl; }

 

    template <classT1,class T2>

    template <classY>

    void classname<T1, T2>::prin(Y str) { cout <<str << endl; }

    使用template主要是让T1等有定义出来,其余就和内部类一样。模板就和正常的数据一样,那自然也可以    template<template<classTT> class th, class T1,class T2> class th2 {};

当然友元函数也可以friend void show(T1,T2);//类里面声明

template <classT1,class T2>//类外定义

void show(T1t1, T2 t2) { cout << t1 + t2 << endl; }

template<class T>起到传递类型的作用

 

 

 

第九章         友元异常和其他

友元类:

当定义为友元类时候,友元类可以访问此类的私有成员,定义友元类不用说明其存在

class A

{

public:

    friend class B;

};

class B

{

 

};

但是竟可能不要定义友元类,可以通过友元函数去处理问题。

异常:

Abort()和exit()的区别是,exit()会刷新文件缓冲区,但是不会回显消息。

Void fun()throw(数据类型);

Try

{

    fun();

}

Catch(数据类型 e)

{

    //处理程序

}

异常处理的原理是,首先会让异常的地方throw,然后try{}块结束释放内存,当然throw的数据是异常数据的重新的备份,它在发现异常的时候,将抛出的数据进行了复制,然后抛出这个数据。Catch块对应数据类型捕捉异常,之后进行异常的处理。这就是堆栈饥解退。

一般的函数调用是这样的,比如a调用b,那b函数就会在堆栈的顶端,同时顶端的栈堆将会为从a传递进来的参数和b自己创建的变量以及返回地址分配内存。如果b再调用c也是如此,在b调用完成的时候,堆栈将会释放内存,根据返回地址找到a的位置,继续执行下面的语句。

异常处理的基类应该放在最后一个catch里面,因为放在前面将会捕捉派生的对象。

如果不知道catch的对象类型,可以使用…代替

 

RTTI(运行阶段类型识别)只是适用于包含虚函数的类,因为也只有虚函数才去区分谁是谁

dynamic_cast安全转换对象

tabletennisplayer* t1=newtabletennisplayer();

rateplayer *r1 = new rateplayer("hello","hello",false,2);

t1 = dynamic_cast<tabletennisplayer *>(r1);//安全转换,失败返回空指针

t1->name();

ciwai

const_cast()把const对象类型的数据变成普通的,地址一样,然后可以进行修改

staic_cast/reinterpre_cast

 

typeid()可以知道对象的所属类型

if (typeid(rateplayer)== typeid(*t1)) { cout<< "\nthey are same\n"; cout<< typeid(*t1).name()<< endl << typeid(*t1).hash_code() << endl; }

 

 

 

第十章         string类和标准模板库

string类:

不解释

智能指针:

Auto_ptr必须显示的构造,还有就是智能是定义单个变量不能使数组,因为delete而不是delete[],会有让权操作,也就是第一个指针的内容赋值给下一个时,第一个失效。注意:智能指针是自动调用delete,也就是堆栈里面的元素,所以不能把自变量的地址赋给智能指针。

auto_ptr<int> i1(newint);//必须显示的构造,而且不能使数组,因为数组使用delete[]来释放内存。

int *ptr = new int(3);

    i1= auto_ptr<int>(ptr);

    cout<< *i1 << endl;*

 

STL:

序列式容器vector有超尾指针end,有begin,size(),pop_back(),push_back(),erase(),insert()

vector<int>::iterator int_iterator;

    i1.push_back(3);//在vectror后面添加元素

    i1.push_back(2);

    i1.push_back(1);

    i1.pop_back();

    int_iterator= i1.begin();

    cout<<"元素的数量:"<< i1.size()<<"\n"<< "现在可以容纳的数量:"<<i1.capacity()<< endl;

    cout<< "vector :\n";

    while (int_iterator !=i1.end())

    {

        cout<< *int_iterator << endl;

        int_iterator++;

    }

    cout<< *(--int_iterator) << endl;

    i1.erase(i1.begin(),i1.begin() + 2);//erase清除前面两个元素

    cout<< "erase result:\n";

    int_iterator= i1.begin();

    while (int_iterator !=i1.end())

    {

        cout<< *int_iterator << endl;

        int_iterator++;

    }

vector<int> int_temp = {1,3,2,4,5 };

    cout<< "have insert :\n";

    i1.insert(i1.begin(),int_temp.begin(),int_temp.end());//insert()插入元素

    for (int_iterator =i1.begin(); int_iterator != i1.end(); int_iterator++) { cout<< *int_iterator << endl; }

当然可以接受stl的算法,比如for_each(),random_shuffle(),sort()

cout << "for_each():\n";

    std::for_each(int_temp.begin(),int_temp.end(), display);//循环传递元素给作为函数参数

 

    cout<< "random_shuffle();\n";

    std::random_shuffle(int_temp.begin(),int_temp.end());//打乱顺序

    std::for_each(int_temp.begin(),int_temp.end(), display);

   

    cout<< "sort()\n";

    std::sort(int_temp.begin(),int_temp.end());

    std::for_each(int_temp.begin(),int_temp.end(), display);

    std::random_shuffle(int_temp.begin(),int_temp.end());

    cout<< "重新排序\n";

    std::sort(int_temp.begin(),int_temp.end(), compa);//进行排序

    std::for_each(int_temp.begin(),int_temp.end(), display);

voiddisplay(inta) { cout << a << endl; }

bool compa(int &a,int &b) { return a > b ?true : false; }

sort里面既然接受地址那样,那下面也成立

cout << "对数组进行的操作\n";

    int arra[5] = {1,9,0,1,3 };//stl算法对数组进行操作

std::sort(arra,arra + 5,compa);

迭代器(广义上来讲是一种指针):

输入,输出,正向,双向,随机迭代器

Copy()传达的时赋值的操作

std::ostream_iterator<int,char> out(cout,"\n");

    std::copy(arra,arra + 5, int_temp.begin());

    std::copy(int_temp.begin(),int_temp.end(), out);

cout << "元素反置\n";

    std::copy(int_temp.rbegin(),int_temp.rend(), out);

 

    cout<< "向后插入元素\n";

    copy(arra,arra + 3, std::back_insert_iterator<vector<int>>(int_temp));

    copy(int_temp.begin(),int_temp.end(), out);

    cout<< "向前抽入元素" << endl;

    copy(arra,arra + 3, std::insert_iterator<vector<int>>(int_temp,int_temp.begin()));

    copy(int_temp.begin(),int_temp.end(), out);

联合容器:

Set和muitimap等,set的操作set_union(),set_intersection(),set_diffrence()

std::set<int> A(arra,arra+5);//set

    cout<< "A is\n";

    std::copy(A.begin(),A.end(), out);

    std::set<int>B;

    B.insert(9);

    B.insert(2);

    cout<< "B is \n";

    std::copy(B.begin(),B.end(), out);

    std::set<int>C;

    cout<< "set_union()\n";

    std::set_union(A.begin(),A.end(), B.begin(), B.end(), std::insert_iterator<std::set<int>>(C, C.begin()));

    //std::copy(C.begin(), C.end(), out);

    std::set_union(A.begin(),A.end(), B.begin(), B.end(), out);

 

    typedef std::pair<int, std::string>Pair;

    std::multimap<int, std::string>mapcode;

    mapcode.insert(Pair(1, "hello"));

    mapcode.insert(Pair(2, "everyone"));

    *out++= mapcode.size();

    cout<< endl;

    std::pair<std::multimap<int, std::string>::iterator, std::multimap<int, std::string>::iterator> range;

    range=mapcode.equal_range(1);

    for (std::multimap<int, std::string>::iterator it = range.first;it!= range.second; ++it) { cout<< (*it).second << endl; }

 

 

 

第十一章  输入输出和文件

输入流和输出流:ios_base->ios->各种流

缓冲区为了更有效率的输出数据,先把数据囤积起来一起输出

输出的函数有<<,put(单个字符),write(数组的起始地址,数组的位置)

Flush强制刷新缓冲区

另外有格式控制的头文件,width(10),fill(‘#’),setf(ios_base::xxx)

流的状态(eodbit,badbit,failbie,goodbit,eof(),bad(),fail(),rdstate(),clear(),setstate())

 

文件的操作

注:默认情况下以ios_base::trunc清除文件所有的内容打开文件,这样这个就不能和in连用

基本:ios_base::in/out/ate 读文件/写入文件/在末尾写文件  

追加:ios_base::app/trunc

此外可以二进制的形式打开文件

为了写入和读出的方便,用二进制的方式写入和读出来,但是对于有虚函数的对象不适用

自由存储:seekg、seekp()其中的参数有正整数向右移动,负整数向后移动,ios_base::beg/end/cur,检查文件指针的位置tellg/tellp()

 

//temp.cpp包含main()文件

#include<iostream>

#include<fstream>

void main()

{

    const char* file = "cxq.txt";

    std::ifstream fin(file);

    char ch;

    if (fin.is_open())

    {

        while (fin.get(ch))

        {

            std::cout<< ch;

        }

    }

    fin.close();

    std::ofstream fout(file);

    if (!fout.is_open()) {std::cerr<< "Can`t open"<< file << " file for output.\n"; exit(EXIT_FAILURE); }

    char str[] = "我是专业路过\n";

    fout<< str << std::endl;

    fout.close();

    fin.clear();//清空输入流

    fin.open(file);

    while (fin.get(ch))

    {

        std::cout<< ch;

    }

    fin.close();

   

}

 

//temp.cpp包含main()文件

#include<iostream>

#include<fstream>

struct  student

{

    int num;

    char name[20];

    float score;

};

void main()

{

    student st1{1500730142,"zylg",99.9};

    student st2{ 1500730141,"zzz",1.1 };

    char *file = "student.dat";

    std::fstream fin;

    int place = (sizeof  st2);

    fin.open(file,std::ios_base::out|std::ios_base::in|std::ios_base::app|std::ios_base::binary);

    fin.write((char *)&st2, sizeof st2);

    fin.seekg(-place,std::ios_base::end); //访问的位置是最后一个结构体的位置

    while (fin.read((char*)&st2,sizeof st1))

    {

       

        std::cout<< st2.num << st2.name << st2.score << std::endl;

    }

    fin.close();

   

   

   

}


转载于:https://www.cnblogs.com/zylg/p/9251768.html

本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

C++primer总结 的相关文章

  • R语言学习笔记:分析学生的考试成绩

    孩子上初中时拿到过全年级一次考试所有科目的考试成绩表 正好可以用于R语言的统计分析学习 为了不泄漏孩子的姓名 就用学号代替了 感兴趣可以下载测试数据进行练习 num class chn math eng phy chem politics
  • C++中的namespace

    namespace中文意思是命名空间或者叫名字空间 传统的C 只有一个全局的namespace 但是由于现在的程序的规模越来越大 程序的分工越来越细 全局作用域变得越来越拥挤 每个人都可能使用相同的名字来实现不同的库 于是程序员在合并程序的
  • [原]Pro*C介绍-内嵌SQL

    Translate by Z Jingwei Document address http www db stanford edu ullman fcdb oracle or proc html Pro C介绍内嵌SQL 概要 Pro C语法
  • 多线程系列之——事件内核对象

    所有内核对象里面事件内核对象是最简单的一个 它包括一个使用计数 还有两个布尔值 一个布尔值用来表示事件是手动重置事件还是自动重置事件 另一个布尔值表示当前是否处于触发状态 当一个手动重置事件被触发的时候 所有等待该事件的线程都能变成调度状态
  • 解决“17: 错误:程序中有游离的‘\240’,\302’

    参考链接 https blog csdn net asuphy article details 54602426 执行如下命令即可 sed i s o240 o302 g dy haikang test cpp
  • C语言pcre库的使用及验证IP地址的合法性

    PCRE是一个用C语言编写的正则表达式函数库 它十分易用 同时功能也很强大 性能超过了POSIX正则表达式库和一些经典的正则表达式库 在使用PCRE库时 首先肯定是需要安装pcre的 不过一般的系统都会有自带的PCRE库 不过如果想使用最新
  • C++工程师复习题

    一 auto ptr 类使用必须满足下列限制 1 不要使用 auto ptr 对象保存指向静态分配对象的指针 2 不要使用两个 auto ptrs 对象指向同一对象 3 不要使用 auto ptr 对象保存指向动态分配数组的指针 4 不要将
  • 经典面试题之new和malloc的区别

    new和malloc的区别是C C 一道经典的面试题 我也遇到过几次 回答的都不是很好 今天特意整理了一下 0 属性 new delete是C 关键字 需要编译器支持 malloc free是库函数 需要头文件支持 1 参数 使用new操作
  • GDAL多光谱与全色图像融合简单使用

    目录 简述 C 代码 效果对比 GDAL融合效果和原始多光谱波段对比 GDAL融合效果和原始全色波段对比 ARCGIS融合效果与原始全色和多光谱对比 GDAL融合效果与ArcGIS融合效果对比 简述 最近在GDAL的代码中看见了gdalpa
  • Lua和C++交互总结(很详细)

    出处 http blog csdn net shun fzll article details 39120965 一 lua堆栈 要理解lua和c 交互 首先要理解lua堆栈 简单来说 Lua和C c 语言通信的主要方法是一个无处不在的虚拟
  • vector,list,deque区别

    http blog csdn net renkaihao article details 6803866 vector和built in数组类似 它拥有一段连续的内存空间 并且起始地址不变 因此它能非常好的支持随即存取 即 操作符 但由于它
  • Trace Function Enter, Exit and Leave

    http developer nokia com community wiki Trace Function Enter Exit and Leave
  • Dev-C++之开启装逼效果

    Dev C 是个不错的C IDE 在10年前 它是很不错 在现在 它是个以界面丑陋和调试像吃粑粑这两点著称 如下图 实在是丑到离谱 丑到无法忍受 可是没办法呀 人家CCF规定比赛用这个 你个小蒟蒻吵什么 我现在就来讲讲怎么把你的Dev C
  • C++:指向类的成员的指针

    引 想必接触过C的朋友们对C语言中指针的概念已经有了深入的了解 如果初步进行了解的朋友可以看一下 C语言基础学习笔记 指针展开来讲的基本知识点包括 指针的概念 指针的定义和初始化及简单使用 指针函数和函数指针 有关指针函数和函数指针的内容上
  • 【C/C++】 - Linux下查找函数头文件 以及 man命令拓展

    背景 比如现在需要找C语言 sleep函数的头文件 使用man来查找 可以先man sleep 可以发现出来的默认是sleep 1 是一个User Commands 明显不是我们需要的 这里提示了 看sleep 3 那我们查看下sleep
  • 一个简单的参数帮助框架,c实现

    文章目录 具体实现如下 include
  • C++中的并发多线程网络通讯

    C 中的并发多线程网络通讯 一 引言 C 作为一种高效且功能强大的编程语言 为开发者提供了多种工具来处理多线程和网络通信 多线程编程允许多个任务同时执行 而网络通信则是现代应用程序的基石 本文将深入探讨如何使用C 实现并发多线程网络通信 并
  • C 语言运算符详解

    C 语言中的运算符 运算符用于对变量和值进行操作 在下面的示例中 我们使用 运算符将两个值相加 int myNum 100 50 虽然 运算符通常用于将两个值相加 就像上面的示例一样 它还可以用于将变量和值相加 或者将变量和另一个变量相加
  • C++ 中 const 和 constexpr 关键字解析:常量、函数和指针

    很多 C 的初学者看到 const 这个关键字的第一反应都是一头雾水 主要是因为 const 可 以出现在很多的位置 以及后面加入的 constexpr 更是常常感到困惑 今天就为大家一一解释出现它们的含义和以及作用 const 关键字 c
  • C中的内存使用问题

    请帮忙 操作系统 Linux 其中 sleep 1000 中 此时 top 显示Linux任务 给我写了7 7 MEM使用 valgrind 未发现内存泄漏 我明白 写得正确 所有 malloc 结果都是 NULL 但是为什么这次 睡眠 我

随机推荐

  • 多租户系统设计

    多租户系统设计 SaaS 的系统分级 SaaS 系统架构成熟度模型的 5 个级别 从 混乱 到 乌托邦 第 0 级 混乱 每次新增一个客户 都会新增软件的一个实例 第 1 级 受控的混乱 所有客户都运行在软件的同一个版本上 而且任何的定制化
  • 当在浏览器中输入一个域名后,会发生什么

    今天 去哪儿网Geely老师分享了他在校招时的一个面试题 当输www qunar com时发生了什么 真不是做广告哈 因为学的并没有很扎实 不能更深更广的分析这个问题 遂 百度一下 发现这篇文章并转载保存下来 同时也分享一下 希望大家可以更
  • vue-cli3.0打包时如何忽略某个第三方依赖包

    前几天接到了用vue重构某个业务模块的需求 常规开发不做讨论 但是在打包时需要排除业务中使用的某个第三方依赖包 代码如下 main js import Vue from vue import Cesium from cesium Cesiu
  • 解决Win7启动时出现“windows未能启动。原因可能是最近更改了硬件或软件”的问题

    搜索资料的时候发现个小问题 问题描述 在给ThinkPad T490做win7系统时 出现了 windows未能启动 原因可能是最近更改了硬件或软件 的问题 一直启动不来 在系统盘微PE中甚至还会出现 0x490 找不到元素 的问题 如何来
  • cuda安装笔记

    更新2023 3 4 我笔记本用vs编译后老是提示no kernel image is available for execution on the device 一直以为是驱动版本太高了或者cudatoolkit版本太高了 后来才知道是版
  • 【数据挖掘】知识点总结

    一 绪论 什么是数据挖掘 就是通过算法从大量的数据中搜索隐藏在其中的信息 数据挖掘的基本任务 聚类分析 异常检测 关联分析和预测建模 高维性和维灾难 随着维度的增加计算复杂度也随之增加 二 数据 不同的属性类型 标称 例如 邮政编码 定性数
  • 大数据应用——Linux常用的命令

    帮助命令 1 基本语法 help 命令 功能描述 获得shell内置命令的帮助信息 2 案例实操 1 查看cd命令的帮助信息 root hadoop01 help cd 常用快捷键 常用快捷键 功能 ctrl c 停止进程 ctrl l 清
  • Python(十五)读取Excel

    今天来实战演示如何封装读取Excel方法 第一步 准备一个Excel文件 sheet页命名为 login 学习技术交流群 704807680 第二步 编写代码找到Excel文件所在的文件夹路径 path os path dirname os
  • 机器学习算法——混淆矩阵(Confusion Matrix)之鸢尾花实例

    一 理论 什么是混淆矩阵 其实就是把所有类别的预测结果与真实结果按类别放置到了同一个表里 在这个表里我们可以清楚地看到每个类别正确识别的数量和错误识别的数量 混淆矩阵在什么情况下最好呢 答案是类别不平衡时 混淆矩阵是除了ROC曲线和AUC之
  • chatGPT高考作文

    百花齐放 春满人间 吹灭别人的灯 并不会让自己更加光明 阻挡别人的路 也不会让自己行得更远 这是一句古老而智慧的话语 告诉我们要尊重和包容他人 要与人和睦相处 要共同进步 同样的道理 也适用于文化的交流和发展 文化是一个民族的灵魂 是一个国
  • 华为OD机试真题-不爱施肥的小布

    题目描述 某农场主管理了一大片果园 fields i 表示不同果林的面积 单位 m 2 现在要为所有的果林施肥且必须在n天之内完成 否则影响收成 小布是果林的工作人员 他每次选择一片果林进行施肥 且一片果林施肥完后当天不再进行施肥作业 假设
  • C++复合类型

    1 数组 数组声明应该指出元素类型 数组名和元素个数 数组的初始化需要遵循以下规则 a 只有定义数组时才能使用初始化 此后就不能使用了 也不能将一个数组赋给另一个数组 int narray1 4 1 2 3 4 int narray2 4
  • 操作系统 实验二 银行家算法

    题目描述 已知进程 P0 P1 P2 P3 P4 有三类系统资源A B C的数量分别为10 5 7 在T0时刻的资源分配情况如下图所示 1 若进程P1请求资源 发出请求向量Request1 1 0 2 编写程序用银行家算法判断系统能否将资源
  • 【javascript-基础小练习】角度转弧度,已知角度90,转成弧度?

    角转弧度的公式为 jiao 180 pai hu 假设pai的值为 3 14
  • 数据库的事务及变量声明方法

    事务 简单来说事务就是为了保持数据一致性的一种手段 在事务中的sql语句作为一个整体一起向系统提交 要么都执行 要么都不执行 可以回滚到原来的状态 事务的语法 开始事务 begin tran 或者transaction 提交事务 commi
  • Spring为什么不推荐你使用@Autowired ?

    Spring为什么不推荐你使用 Autowired 我们总能发现当使用IDEA写代码的时候 Autowired注解会报黄 我们把鼠标悬停在上面 可以看到这个如下图所示的警告信息 当我们按住alt 回车键 idea就会帮我们修改成这样 我向来
  • 微服务架构

    3 注册中心与服务发现 前言 1 服务发现基础知识 1 1 注册中心与服务发现的联系 1 2 使用 DNS 与负载均衡器发现服务的弊端 1 3 云中的服务发现应该具备的特点 1 4 服务发现架构 1 5 服务治理的概念 1 6 服务注册的概
  • Linux服务器(centos7)中Word转换PDF,文档出现中文乱码或方格【亲测可用,已解决】

    提示 在centos服务器使用aspose word转换word文件为pdf的时候只有中文乱码或则方格 但是在win服务器上使用可以正常转换 本次文章主要解决字体缺失问题 目录 前言 一 在linux服务器上生成的pdf都是这种格式的 二
  • 信号和槽函数的扩展

    信号和槽函数的扩展 一个信号连接多个槽函数 一个槽函数连接多个信号 信号连接信号 一个信号可以连接多个槽函数 发送一个信号有多个处理动作 需要写多个connect 连接 槽函数的执行顺序和信号的发射顺序相同 QT5中 信号的接收者可以是一个
  • C++primer总结

    目录 第一章 数据处理 2 整形 2 第二章 复合类型 3 数组 3 字符串 4 枚举 5 指针 5 第三章 函数的使用 6 内联函数 6 默认参数 6 函数的重载 7 函数的模板 7 第四章 内存模型和名称空间 7 文件的单独存放 7 变