首页
社区
课程
招聘
[原创]C++ 5分钟速成
2022-9-14 14:16 21761

[原创]C++ 5分钟速成

2022-9-14 14:16
21761

2.0 C++之新特性

1
2
3
4
5
int x(100)意思是x=100;
 
C++的输入输出方式
输入:cin>>x;意思是输入字符串或者数字到变量值x
输出:cout<<x<<endl;意思是输出变量x里面的内容,并且换行;

2.1 C++之命名空间namespace

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
#include <iostream>
using namespace std;
int main()
{
    cout<<"Hello,World!"<<endl;
    return 0;
}
"using"使用命名空间;
"::"代表作用域;
自定义的命名空间,和使用自定义的命名空间
#include <iostream>
using namespace std;
namespace A
{
    int x = 1;
    void func()
    {
        cout << "A namespace" << endl;
    }
}
 
using namespace A;
int main()
{
    func();
    A::x = 3;
    cout << A::x << endl;
    A::func();
    return 0;
 
}

2.2 C++面向对象

面向对象的三大特征是继承,多态和封装

2.2.1 类和对象

类用于指定对象的形式,它包含了数据表示法和用于处理数据的方法。类中的数据和方法称为类的成员。函数在一个类中被称为类的成员

从类中实例化对象分两种方法,一种是从栈中实例化对象,一种是从堆中实例化对象。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
#include <iostream>
#include <string>
using namespace std;
 
class Dog
{
public:
    string name;
    int    age;
    void run()
    {
        cout << "小狗的名字是:" << name << "," << "年龄是:" << age << endl;
    }
};
 
int main()
{
    Dog dog1;//从栈中实例化了一个对象dog1;
    dog1.name = "旺财";
    dog1.age = 2;
    dog1.run();
 
    Dog* dog2 = new Dog();//从堆中实例化队像,使用关键字new的都是从堆中实例化队像
    if (dog2==NULL)//从堆中实例化对象需要开辟内存,指针会指向那个内存,如果 new 没有申请内存成功,p 即指向 NULL,程序就自动退出,下面的就不执行了,写这个是为了严谨。
    {
        return 0;
    }
    dog2->name = "富贵";
    dog2->age = 1;
    dog2->run();
    delete dog2;
    dog2 = NULL;
    return 0;
}

2.2.1.1 构造函数和析构函数

构造函数的特点如下:

(1) 构造函数必须与类名同名;

(2) 可以重载,(重载?新概念,后面学到什么是重载。);

(3) 没有返回类型,即使是 void 也不行。

析构函数的特点如下:

(1) 析构函数的格式为~类名();

(2) 调用时释放内存(资源);

(3) ~类名()不能加参数;

(4) 没有返回值,即使是 void 也不行。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
#include <iostream>
#include <string>
using namespace std;
 
class Dog
{
public:
    Dog();
    ~Dog();
};
 
int main()
{
    Dog dog;
    cout << "构造和析构函数示例" << endl;
    return 0;
 
}
Dog::Dog()//类的函数可以在类里实现,也可以在类外实现,不过在类外实现时需要使用“::”,此时我们把类的构造函数定义在类的外面
{
    cout << "构造函数执行!" << endl;
}
 
Dog::~Dog()
{
    cout << "析构函数执行!" << endl;
}

2.2.1.2 this指针

每个对象都拥有一个 this 指针,this 指针记录对象的内存地址。在 C++中,this 指针是指向类自身数据的指针,简单的来说就是指向当前类的当前实例对象

关于类的 this 指针有以下特点:

(1) this 只能在成员函数中使用,全局函数、静态函数都不能使用 this。实际上,成员函数

默认第一个参数为 T * const this。也就是一个类里面的成员了函数 int func(int p),func 的原

型在编译器看来应该是 int func(T * const this,int p)。

(2) this 在成员函数的开始前构造,在成员函数的结束后清除。

(3) this 指针会因编译器不同而有不同的放置位置。可能是栈,也可能是寄存器,甚至全局变量。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
#include <iostream>
#include <string>
using namespace std;
 
class Dog
{
public:
    string name;
    void func();
};
 
int main()
{
    Dog dog;
    dog.func();
    return 0;
}
 
void Dog::func()
{
    this->name = "旺财";
    cout << "小狗的名字叫:" << this->name << endl;
}

2.2.2 继承

已有的类称为基类,新建的类称为派生类

1. 公有继承(public):当一个类派生继承公有基类时,基类的公有成员也是派生类的公有成员,基类的保护成员也是派生类的保护成员,基类的私有成员不能直接被派生类访问,但是可以通过调用基类的公有和保护成员来访问。

2. 保护继承(protected): 当一个类派生继承保护基类时,基类的公有和保护成员将成为派生类的保护成员。

3. 私有继承(private):当一个类派生继承私有基类时,基类的公有和保护成员将成为派生类的私有成员。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
#include <iostream>
#include <string>
using namespace std;
 
class Animal
{
public :
    string color;
    int weight;
};
 
class Dog :public Animal //Animal 作为基类,Dog 作为派生类。Dog 继承了 Animal 类。访问修饰符为 public(公有继承)
{
public:
    string name;
    int age;
    void fun();
};
 
int main()
{
    Dog dog;
    dog.name = "旺财";
    dog.age = 2;
    dog.color = "黑色";
    dog.weight = 120;
    cout << "狗的名字叫:" << dog.name << endl;
    cout << "狗的年龄是" << dog.age << endl;
    cout << "狗的毛发颜色:" << dog.color << endl;
    cout << "狗的体重是:" << dog.weight << endl;
    return 0;
}

2.2.3 重载

2.2.3.1 函数重载

在同一个作用域内,可以声明几个功能类似的同名函数,但是这些同名函数的形式参数(指参数的个数、类型或者顺序)必须不同。我们不能仅通过返回类型的不同来重载函数。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
#include <iostream>
#include <string>
using namespace std;
 
class Dog
{
public:
    string name;
    void getWeight(int weight)//写了一个方法 getWeight(int weight),以 int 类型作为参数。
    {
        cout << this->name << "的体重为:" << weight <<"KG" << endl;
    }
    void getWeight(double weight)//以相同的函数名 getWeight,不同的参数类型 double weight,这样就构成了函数重载
    {
        cout << this->name << "的体重为:" << weight << "KG" << endl;
    }
};
 
int main()
{
    Dog dog;
    dog.name = "旺财";
    dog.getWeight(10);//分别传进参数不同的参数,程序就会匹配不同的重载函数
    dog.getWeight(10.5);
    return 0;
}

2.2.3.2 运算符重载(+-*/等运算符)

运算符重载的实质就是函数重载或函数多态,目的在于让人能够用同名的函数来完成不同的基本操作。要重载运算符,需要使用被称为运算符函数的特殊函数形式,运算符函数形式:operatorp(argument-list),operator 后面的'p'为要重载的运算符符号。重载运算符的格式如下:

<返回类型说明符> operator <运算符符号>(<参数表>)

{

<函数体>

}

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
#include <iostream>
#include <string>
using namespace std;
 
class Dog
{
 
public:
    int weight;
    Dog operator+(const Dog& d)
    {
        Dog dog;
        dog.weight = this->weight + d.weight;//重载“+”运算符,注意函数必须与类名同名,把 Dog 对象作为传递,使用this 运算符进行访问。然后返回一个 dog 对象。
        return dog;
    }
};
 
int main()
{
    Dog dog1,dog2,dog3;
    dog1.weight = 10;
    dog2.weight = 20;
    dog3 = dog1 + dog2;
    cout << "第三只狗的体重是:" << dog3.weight << endl;
}

2.2.4 多态

C++多态意味着调用成员函数时,会根据调用函数的对象的类型来执行不同的函数;

形成多态必须具备三个条件:

1. 必须存在继承关系;

2. 继承关系必须有同名虚函数(其中虚函数是在基类中使用关键字 virtual 声明的函数,在派

生类中重新定义基类中定义的虚函数时,会告诉编译器不要静态链接到该函数);

3. 存在基类类型的指针或者引用,通过该指针或引用调用虚函数。

这里我们还需要理解两个概念:

虚函数:

是在基类中使用关键字 virtual 声明的函数。在派生类中重新定义基类中定义的虚函数时,

会告诉编译器不要静态链接到该函数。我们想要的是在程序中任意点可以根据所调用的对象类

型来选择调用的函数,这种操作被称为动态链接,或后期绑定。虚函数声明如下:virtual

ReturnType FunctionName(Parameter) 虚函数必须实现,如果不实现,编译器将报错

纯虚函数:

若在基类中定义虚函数,以便在派生类中重新定义该函数更好地适用于对象,但是您在基

类中又不能对虚函数给出有意义的实现,这个时候就会用到纯虚函数。纯虚函数声明如下:

virtual void funtion1()=0; 纯虚函数一定没有定义,纯虚函数用来规范派生类的行为,即接口。

包含纯虚函数的类是抽象类,抽象类不能定义实例,但可以声明指向实现该抽象类的具体类的

指针或引用。

总结多态:多态定义标识是virtual,基类与派生类中必须是继承且有同名虚函数,用基类类型的指针或者引用为载体指向实例化派生类中的虚函数;

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
#include <iostream>
#include <string>
using namespace std;
 
class Animal/* 定义一个动物类 */
{
public:
    virtual void run()
    {
        cout << "Animal的run方法" << endl;
    }
};
 
class Dog :public Animal
{
public:
    void run()
    {
        cout << "Dog的run方法" << endl;
    }
 
};
 
class Cat :public Animal/* 定义一个猫类,并继承动物类 */
{
public :
    void run()
    {
        cout << "Cat的run方法" << endl;
    }
};
 
int main()
{
    Animal *animal;/* 声明一个 Animal 的指针对象,注:并没有实例化 */
    Dog dog;/* 实例化 dog 对象 */
    Cat cat;
    animal = &dog;/* 存储 dog 对象的地址 */
    animal->run();/* 调用 run()方法 */
    animal = &cat;
    animal->run();
    return 0;
}

都有一个 run()方法。其中我们可以看到基类 Animal 类的 run()

方法前面加了关键字 virtual。这样让基类 Animal 类的 run()方法变成了虚函数。在这个例子里

我们可以知道是 虚函数是 C++ 中用于实现多态(polymorphism) 的机制。 核心理念就是通过基类访问派生类定义的函数。

2.2.5 数据封装

数据封装是一种把数据和操作数据的函数捆绑在一起的机制, 数据抽象是一种仅向用户暴

露接口而把具体的实现细节隐藏起来的机制,C++ 通过创建类来支持封装和数据隐藏(public、protected、private)。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
#include <iostream>
#include <string>
using namespace std;
 
class Dog
{
public:
    string name;
    Dog(int i = 0)//在构造函数里初始化 total 的数量,不初始化 total 的数量默认是随 int 类型的数。所以我们需要在构造函数里初始化,也体现了构造函数的功能,一般是在构造函数里初始化。不要在类内直接赋值初始化,有可能有些编译器不支持。
    {
        total = i;
    }
    void addFood(int number)//addFood(int number),在这个方法里,将获得的食物份数赋值给 total。
    {
        total = total + number;
    }
    int getFood()//getFood(),在这个方法里,将返回食物的总份数。通过调用这个方法,即可访问私有成员的 total 总数。
    {
        return total;
    }
private:
    int total;
};
 
int main()
{
    Dog dog;
    dog.name = "旺财";
    dog.addFood(2);
    dog.addFood(3);//添加食物的份数。
    cout << dog.name << "总共获得了" << dog.getFood() << "份食物。" << endl;//打印食物的总份数。
    return 0;
}

2.2.6 数据抽象

数据抽象是指,只向外界提供关键信息,并隐藏其后台的实现细节,即只表现必要的信息而不呈现细节。数据抽象是一种依赖于接口和实现分离的编程(设计)技术。

数据抽象的好处:

1. 类的内部受到保护,不会因无意的用户级错误导致对象状态受损。

2. 类实现可能随着时间的推移而发生变化,以便应对不断变化的需求,或者应对那些要求不改变用户级代码的错误报告。

2.2.7 接口(抽象类)

接口描述了类的行为和功能,而不需要完成类的特定实现。

如果类中至少有一个函数被声明为纯虚函数,则这个类就是抽象类。纯虚函数是通过在声明中使用 "= 0" 来指定的。

设计抽象类(通常称为 ABC)的目的,是为了给其他类提供一个可以继承的适当的基类。抽象类 不能被用于实例化对象,它只能 作为接口使用。如果试图实例化一个抽象类的对象,会导致编译错误。

因此,如果一个 ABC 的子类需要被实例化,则必须实现每个虚函数,这也意味着 C++ 支持使用 ABC 声明接口。如果没有在派生类中重写纯虚函数,就尝试实例化该类的对象,会导致编译错误。可用于实例化对象的类被称为具体类。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
#include <iostream>
#include <string>
using namespace std;
 
class Animal
{
public:
    virtual void run() = 0;
 
};
 
class Dog :public Animal
{
public:
    void run()
    {
        cout << "Dog的run方法" << endl;
    }
};
 
class Cat:public Animal
{
public:
    void run()
    {
        cout << "Cat的run方法" << endl;
    }
};
 
int main()
{
    Dog dog;
    Cat cat;
    dog.run();
    cat.run();
    return 0;
}

2.2.8 STL

C++ 标准模板库的核心包括以下三个组件:

(1)容器:

容器是用来管理某一类对象的集合。C++ 提供了各种不同类型的容器,比如 deque、list、vector、map 等。

(2)算法:

算法作用于容器。它们提供了执行各种操作的方式,包括对容器内容执行初始化、排序、搜索和转换等操作。

(3)迭代器:

迭代器用于遍历对象集合的元素。这些集合可能是容器,也可能是容器的子集。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
#include <iostream>
#include <vector>
#include <string>
using namespace std;
 
int main()
{
    vector<int> vec;//创建一个向量存储 int
    int i;
    cout << "vector size = " << vec.size() << endl;//显示vector的原始大小
    for (i = 0; i < 5; i++)//插入五个值到向量中
    {
        vec.push_back(i);
    }
    cout << "extended vector size = " << vec.size() << endl;//显示vec扩展后的大小
 
    for (i=0;i<vec.size();i++)//访问向量中的5个值
    {
        cout << "value of vec[" << i << "]" << vec[i] << endl;
    }
 
    //使用迭代器iterator访问值
    vector<int>::iterator v = vec.begin();
    while (v != vec.end())
    {
        cout << "value of v = " << *v << endl;
        v++;
    }
    return 0;
 
}

push_back( ) 成员函数在向量的末尾插入值,如果有必要会扩展向量的大小。

size( ) 函数显示向量的大小。

begin( ) 函数返回一个指向向量开头的迭代器。

end( ) 函数返回一个指向向量末尾的迭代器。


[培训]二进制漏洞攻防(第3期);满10人开班;模糊测试与工具使用二次开发;网络协议漏洞挖掘;Linux内核漏洞挖掘与利用;AOSP漏洞挖掘与利用;代码审计。

最后于 2022-9-14 15:32 被daiweizhi编辑 ,原因: 增加内容
收藏
点赞5
打赏
分享
最新回复 (19)
雪    币: 160
活跃值: (2288)
能力值: ( LV2,RANK:10 )
在线值:
发帖
回帖
粉丝
Yecate 2022-9-14 14:19
2
0
5分钟....
雪    币: 1803
活跃值: (900)
能力值: ( LV3,RANK:20 )
在线值:
发帖
回帖
粉丝
暗月隐落 2022-9-14 22:49
3
0
通过这篇文章深刻认知了,我也大佬的差距,大佬5分钟速成了c++,我 5分钟明白了我是个渣渣,不适合这一行
雪    币: 4468
活跃值: (1476)
能力值: ( LV2,RANK:10 )
在线值:
发帖
回帖
粉丝
qzhiwen 2022-9-15 00:20
4
0
必须有5年功力才能5分钟看懂
雪    币: 3144
活跃值: (1624)
能力值: ( LV2,RANK:10 )
在线值:
发帖
回帖
粉丝
shun其自然 2022-9-15 01:28
5
0
很详细,但是5分钟告诉我,千万不要入此行
雪    币: 3232
活跃值: (2293)
能力值: ( LV2,RANK:10 )
在线值:
发帖
回帖
粉丝
monpea 2022-9-15 08:10
6
0
good
雪    币: 3806
活跃值: (2230)
能力值: ( LV2,RANK:10 )
在线值:
发帖
回帖
粉丝
欣喜 2022-9-15 10:11
7
0
int x(100)意思是x=100;
好奇怪的特性,那如果想把一个变量a的值赋给x,是不是写成int x(a)?
雪    币: 5053
活跃值: (4354)
能力值: ( LV5,RANK:65 )
在线值:
发帖
回帖
粉丝
gamehack 2022-9-15 12:45
8
0
很不错
雪    币: 6113
活跃值: (4021)
能力值: ( LV6,RANK:80 )
在线值:
发帖
回帖
粉丝
黑洛 1 2022-9-15 13:31
9
0
欣喜 int x(100)意思是x=100; 好奇怪的特性,那如果想把一个变量a的值赋给x,是不是写成int x(a)?
虽然但是,这个是已经几乎被淘汰的写法 现在是 int i{100}
雪    币: 216
活跃值: (272)
能力值: ( LV2,RANK:10 )
在线值:
发帖
回帖
粉丝
hzfjl 2022-9-17 21:51
10
0
重新定义5分钟
雪    币: 13
活跃值: (396)
能力值: ( LV12,RANK:300 )
在线值:
发帖
回帖
粉丝
daiweizhi 1 2022-9-19 11:23
11
0
后续还会增加容器,多线程,以及TCP网络部分,目前马上整理完多线程了,到了线程池部分了
雪    币: 4016
活跃值: (5833)
能力值: ( LV7,RANK:102 )
在线值:
发帖
回帖
粉丝
fjqisba 2022-9-19 14:32
12
0
虚假的现代化C++:模板、对象、语法糖。
真正的现代化C++:Go
雪    币: 16150
活跃值: (5921)
能力值: ( LV13,RANK:861 )
在线值:
发帖
回帖
粉丝
大帅锅 4 2022-9-19 14:42
13
0
《如何在五分钟之内放弃C++》
雪    币: 69
活跃值: (7180)
能力值: ( LV9,RANK:335 )
在线值:
发帖
回帖
粉丝
PlaneJun 6 2022-9-19 15:31
14
0

雪    币: 392
活跃值: (3999)
能力值: ( LV2,RANK:10 )
在线值:
发帖
回帖
粉丝
0x太上 2022-10-23 04:13
15
0
daiweizhi 后续还会增加容器,多线程,以及TCP网络部分,目前马上整理完多线程了,到了线程池部分了
wait
雪    币: 576
活跃值: (2035)
能力值: ( LV2,RANK:10 )
在线值:
发帖
回帖
粉丝
kakasasa 2022-10-23 14:16
16
0
感谢分享,提个建议:应该把声明和定义区分一下,楼主的说法是定义和实现。
雪    币: 1378
活跃值: (3067)
能力值: ( LV2,RANK:10 )
在线值:
发帖
回帖
粉丝
风中小筑V 2022-10-25 12:53
17
0
黑魔法模板呢
雪    币: 189
能力值: ( LV1,RANK:0 )
在线值:
发帖
回帖
粉丝
WolfKingDong 2022-11-24 20:26
18
0
谢谢楼主的分享,学习学习
雪    币: 337
活跃值: (296)
能力值: ( LV2,RANK:10 )
在线值:
发帖
回帖
粉丝
xiaofei_net 2023-7-17 19:36
19
0
5分钟还没看完帖子。。。
雪    币: 310
活跃值: (631)
能力值: ( LV2,RANK:10 )
在线值:
发帖
回帖
粉丝
yszwang 2023-9-2 10:52
20
0
小白看了看似乎还是要多学点才能理解这个
游客
登录 | 注册 方可回帖
返回