C++入门(上)

1.c++关键字

2.命名空间

3.c++输入和输出

4.缺省参数

5.函数重载

6.引用

7.内联函数

8.auto关键字(c++11)

9.基于范围的for循环(c++11)

10.指针空值----nullptr(c++11)

 

0.前言  

 c++是在c的基础上,容纳进去了面向对象编程思想,并增加了许多有用的库,以及编程范式。

学习目标:

       1.c++补充c语言语法的不足,以及c++是如何对c语言设计不合理的地方进行优化的,如:作用域方面,IO方面,函数方面,指针方面,宏方面等。  

       2.为后续类和对象学习打基础

 

1. c++关键字(c++98)

c++总计63个关键字,c语言32个关键字

1f45421af0c740419c879b4f27c2c85b.jpg

 

2. 命名空间

在c/c++中,变量,函数和后面学到的类都是大量存在的,这些变量,函数和类的名称将都存在于全局作用域中,可能会导致很多冲突,使用命名空间的目的是对标识符的名称进行本地化,以避免命名冲突或名字污染,namespace关键字的出现就是针对这种问题的。

#include<stdio.h>

#include<stdlib.h>

int main()

{

    //c语言无法解决这样的命名冲突问题,

    //所以c++提出了namespace来解决

    int rand=10;

    printf("%d\n",rand);

    return 0;

    //编译后报错:"rand":重定义;以前的定义是"函数"

}            

2.1命名空间的定义

定义命名空间,需要使用到namespace关键字,后面跟命名空间的名字,然后接一对{}即可,{}中即为命名空间的成员。

//1.命名空间的正常定义

//a是命名空间的名字

namespace a

{

    //命名空间可以定义变量,函数,结构体

    int rand=10;

    

    int Add(int left,int right)

    {

        return left+right;

    }

    

    struct list

    {

        struct list*next;

        int val;

    };

//2.命名空间可以嵌套

//test.cpp

namespace N1

{

    int a;

    int b;

    int Add(int left, int right)

    {

        return left+right;

    }

    namespace N2

    {

        int Sub(int left,int right)

        {

            return left-right;

        }

    }

        

//3.同一个工程中允许存在多个相同名称的命名空间,编译器最后会合成同一个命名空间中

//一个工程中的test.cpp和test.h 中的N1会被合并成一个

//test.h

namespace N1  

{

    int Mul(int left,int right)

    {

        return left*right;

    }           

}    

注意:一个命名空间就定义了一个新的作用域,命名空间中所有内容都局限于该命名空间中。

2.2命名空间的使用

命名空间中的成员该如何使用?

如果直接使用:

namespace bit

{

    int a=0;

    int b=2;

    int Add(int left,int right)

    {

        return left+right;

    }     

int main()

{

    printf("%d\n",a);

    // 编译报错:"a"未声明的标识符

    return 0;

}                                                                                        

命名空间的三种使用方式:

★加命名空间名称及作用域限定符

int main()

{

    printf("%d\n",bit::a);

    return 0;

★使用using将命名空间中某个成员引进

using bit::b;

int main()

{

    printf("%d\n",bit::a);

    printf("%d\n",b);

    return 0;

}

★使用using namespace命名空间名称引入

using namespace bit;

int main()

{

    printf("%d\n",bit::a);

    printf("%d\n",b);

    Add(10,20);

    return 0;

}

    

3.C++输入和输出

#include<iostream>

//std是C++标准库的命名空间名,C++将标准库的定义实现都放到这个命名空间中

using namespace std;

 

int main()

{

    cout<<"Hello world!!!"<<endl

    return 0;

}

使用:

       1.使用cout标准输出对象(控制台)和cin标准输入对象(键盘)时,必须包含<iostream>头文件以及按命名空间使用方法使用std。

       2.cout和cin是全局的流对象,endl是特殊的c++符号,表示换行输出,他们都包含在<iostream>头文件中。

       3.<<是流插入运算符,>>是流提取运算符。

       4.使用c++输入输出更方便,不需要像printf/scanf输入输出需要手动控制格式。c++的输入输出可以自动识别变量类型。

      5.实际上cout和cin分别是ostream和iostream类型的对象,>>和<<也涉及运算符重载等知识。

注意:早期标准库将所有功能在全局域中实现,声明在.h后缀头文件中,使用只需要包含对应的头文件,后来将其实现在std命名的空间下,为了和c头文件区分,也为了正确使用命名空间,规定c++头文件不使用.h;旧编译器(vc 6.0)中还支持<iostream.h>的格式,后续编译器已不支持,推荐使用<iostream>+std的方式。

#include<iostream>

using namespace std;

int main()

{

    int a;

    double b;

    char c;

    

    cin>>a;

    cin>>b>>c;

    

    cout<<a<<endl;

    cout<<b<<" "<<c<<endl;

    return 0;

 

std命名空间的使用惯例:

std是c++标准库的命名空间,如何展开std更合理?

1.在日常使用中,直接使用using namespace std就可以,这样很方便

2.但是using namespace std展开,标准库就全部暴露出来,如果我们定义跟库重名的类型/对象/函数,就存在冲突问题,该问题在日常练习中很少出现,但是项目开发的代码较多,规模大,就很容易出现。像std::cout这样使用时指定命名空间 + using std::cout展开常用的库对象/类型等方式。

4. 缺省函数

4.1缺省函数的概念

缺省函数就是在声明或定义函数时为参数指定一个缺省值,在调用该函数时,如果没有指定实参,则直接使用该缺省值,否则使用指定的参数。

void func(int a=0)

{

    cout<<a<<endl;

int main()

{

    func();//没有传参时使用默认值

    func(10);//传参时,使用默认实参

    

    return 0;

4.2缺省参数分类

★全省参数

void func(int a=1,int b=4,int c=10)

{

    cout<<"a="<<a<<endl;

    cout<<"b="<<b<<endl;

    cout<<"c="<<c<<endl;

★半缺省参数

void func(int a,int b=3,int c=10)

{

    cout<<"a="<<a<<endl;

    cout<<"b="<<b<<endl;

    cout<<"c="<<c<<endl;

注意:

1.半缺省参数必须从右往左依次给,不能隔着给

2.缺省参数不能在声明和定义中同时出现

3.缺省值必须是常量或者是全局变量

4.c语言不支持

//a.h

void func(int a=10);

 

//a.cpp

void func(int a=10)

{

    ;

//注意:

如果声明和定义同时出现,恰巧两个地方给的值不相同,那么编译器就无法确定用哪个缺省值    

5.函数重载

5.1函数重载的概念

函数重载:是函数的一种特殊情况,c++允许在同一个作用域中声明几个作用类似的同名函数,这些同名函数参数列表(参数类型或参数个数或类型顺序)不同,常用来处理功能类似,数据类型不同的问题。

#include <iostream>

using namespace std;

 

//参数类型不同

int Add(int x,int y)

{

    return x+y;

double Add(double x,double y)

{

    return x+y;

 

//参数个数不同

void fun()

{

    cout<<"void fun()<<endl;

void fun(int x)

{

    cout<<"void fun(int x)"<<endl;

//参数类型顺序不同

void fun(int x,double y)

{

    cout<<void fun(int x,double y)<<endl;

void fun(double x,int y)

{

    cout<<void fun(double x,int y)<<endl;

int main()

{

    Add(3,4);

    Add(5.1,6.7);

    

    fun();

    fun(3);

    

    fun(2,4.5);

    fun(6.3,7);

    

    return 0;

5.2 c++支持函数重载的原理--名字修饰

在c/c++中,程序要运行起来要经历:预处理,编译,汇编,链接

 

    1.实际项目中通常有多个头文件和多个源文件共同构成,由编译链接可知,当a.o中调用b.o中的Add函数是,编译后链接前,a.o的目标文件中找不到Add的地址,由于Add在b.o中定义,所以Add的地址在b.o中。

    2.链接阶段就解决这个问题,链接器看到a.o中调用了Add,但是没有Add的地址,就会到b.o中的符号表中寻找Add的地址,然后链接在一起。

   3.链接时,面对Add函数,链接器根据名字去寻找,每个编译器都有自己的函数名修饰规则

   4. 由于Windows下vs的修饰规则过于复杂,而Linux下g++的修饰规则简单易懂,下面用gcc演示

int Add(int a,int b)

{

    return a+b;

 

void func(int a,double b,int*c)

{

int main

{

    Add(1,2);

    func(1,2,0);

    return 0;

  5. 通过下面我们可以看出gcc的函数修饰后名字不变。而g++的函数修饰后变成【_Z+函数长度+函数名+类型首字母]

采用c语言编译器编译的结果如下

2356146a7b9d41499b56532a561f77ef.jpg

 

 

结论:在linux下,采用gcc编译完成后,函数的名字修饰没有改变

 

采用c++编译器编译的结果如下

dca3e4db22744e9f83ae9028011b8802.jpg

结论:在linux下,采用gcc编译完成后函数的名字发生改变,编译器将函数参数类型信息添加到修改后的名字中

6. 通过这里就理解了C语言没办法支持重载,因为同名函数没办法区分。而C++是通过函数修饰规则来区分,只要参数不同,修饰出来的名字就不一样,就支持了重载。

7. 如果两个函数函数名和参数是一样的,返回值不同是不构成重载的,因为调用时编译器没办法区分。

 

  • 5
    点赞
  • 15
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值