• DAY02 c++对c的扩展


    输出

    语法     

            cout << 输出的内容 1 << 输出的内容 2 << ...
    注意 :
            输出的内容中endl 表示为换行
    示例
            
    #include
    using namespace std;
    int main(int argc, char *argv[])
    {
            cout << "test!" << endl;
            return 0;
    }

    输入

    语法

            cin >> 变量名 1 >> 变量名 2 >> ...
    示例
    #include
    using namespace std;
    int main(int argc, char *argv[])
    {
            cout << "请输入 :";
            #if 0
            int x = 0,y = 0;
            cin >> x >> y;
            cout << "输入的内容是 :x=" << x << " y="<< y << endl;
            #else
            char str[32];
            //cin >> str;
            //cout << "str =" << str << endl;
            cin.getline(str,sizeof(str));
            cout << "str =" << str << endl;
            #endif
            return 0;
    }
    注意
            qt 中有 bug

    C++C的扩展

    1,作用域运算符

    符号 ::

    示例:

    #include
    using namespace std;
    int x = 100;
    int main(int argc, char *argv[])
    {
            int x = 1;
            cout << "x =" << x << endl;
            cout << "::x =" << ::x <
            return 0;
    }

    2,命名空间

    定义
            关键字:namespace
    语法
    namespace [ 名称 ] {
    成员的声明,可以具有初始化的值 ;
    {
    内部嵌套 namespace {};
    }
    {声明成员函数}
    {定义成员函数}
    }
    // 实现 namespace 中声明的函数
    函数返回值类型 命名空间的名称 :: 声明的函数名 ( 形参列表 ){
    }

    示例

    #include
    using namespace std;
    namespace my
    {
    int x = 10;
    void test01();
    void test02()
            {
                    cout << "test02" << endl;
            }
    }
    void my::test01()
    {
            cout << "test01" << endl;
    }
    int main(int argc, char *argv[])
    {
            cout << "my::x =" << my::x << endl;
            my::test01();
            my::test02();
            return 0;
    }
    注意
    1, 命名空间只能在全局范围类定义 ( 命名空间不能定义在函数中 )
    #include
    using namespace std;
    int main(int argc, char *argv[])
    {
            namespace A
             {
                    int a = 10;
            }
            cout << A::a << endl;
            return 0;
    }
    // 此时报错
    2, 命名空间嵌套命名空间 ( 命名空间中可以嵌套命名空间 )
    #include
    using namespace std;
    namespace A {
    int a = 10;
            namespace B
            {
            int b = 20;
            }
    }
    int main(int argc, char *argv[])
    {
            cout << "A::a" <
            cout << "A::B::b" << A::B::b << endl;
            return 0;
    }
    3, 命名空间的开放性(随时添加新的成员
    #include
    using namespace std;
    namespace A
    {
            int a = 10;
    }
    namespace A {
            int a2 = 100;
    }
    int main(int argc, char *argv[])
    {
            cout << "A::a" <
            cout << "A::a2" <
            return 0;
    }
    4, 无名命名空间
    // 无名命名空间,意味着命名空间中的标识符只能在本文件内访问
    #include
    using namespace std;
    namespace {
            int a = 10;
    }
    int main(int argc, char *argv[])
    {
            cout << "::a" <<::a << endl;
            return 0;
    }
    5, 取别名
    #include
    using namespace std;
    namespace XXX{
            int a = 10;
    }
    int main(int argc, char *argv[])
    {
            namespace A = XXX;
            cout << "A::a" <
            return 0;
    }
    using 关键字
    作用 1:using 声明命名空间中的具体成员
    #include
    using namespace std;
    namespace A{
            int a = 10;
            int b = 1;
    }
    int main(int argc, char *argv[])
    {
            //声明命名空间 A 中的 a 变量
            using A::a;
            //使用时可以省略空间名 ::
            cout << "a=" <
            cout << "A::b=" << A::b << endl;
            return 0;
    }
    注意 : 容易造成同范围内的命名冲突
    #include
    using namespace std;
    namespace A{
            int a = 10;
            int b = 1;
    }
    int main(int argc, char *argv[])
    {
            //声明命名空间 A 中的 a 变量
            using A::a;
            //使用时可以省略空间名 ::
            int a = 1;//此时冲突 , 报错
            cout << "A::b=" << A::b << endl;
            return 0;
    }
    作用 2:using 声明成员函数 遇到函数重载
    #include
    using namespace std;
    namespace A{
            int a = 10;
            int b = 1;
            void test()
            {
                    cout << "test01" << endl;
            }
            void test(int x)
            {
                    cout << "test02" << endl;
            }
            void test(int x,int y)
            {
                    cout << "test03" << endl;
            }
    }
    int main(int argc, char *argv[])
    {
    // 声明命名空间 A 中的所有 test 函数
    using A::test;
    test();
    test(10);
    test(1,2);
    return 0;
    }
    作用 3: 声明整个命名空间
    注意:
            当声明的作用域中的变量与成员变量重名, 有冲突
            当声明的作用域中的变量与局部变量重名, 优先使用局部变量
    #include
    using namespace std;
    namespace A{
            int a = 10;
            int b = 1;
            void test()
            {
                    cout << "test01" << endl;
            }
            void test(int x)
            {
                    cout << "test02" << endl;
            }
            void test(int x,int y)
            {
                    cout << "test03" << endl;
            }
    }
    int main(int argc, char *argv[])
    {
    // 声明整个命名空间 A
            using namespace A;
            cout << "a = " << a << endl;
            cout << "b = " << b << endl;
            test();
            test(10);
            test(1,2);
            return 0;
    }

    3,全局变量类型检测增强

    #include
    using namespace std;
    int a = 10;// 赋值并定义
    int a; //c 语言认知为声明 , 通过 ,c++ 认为是定义 , 报错
    int main(int argc, char *argv[])
    {
            return 0;
    }

    4,C++中所有的变量和函数都必须有类型

    C 的自定义函数时,形参变量可以没有数据类型,即为任意类型 , 警告但是可以编译通
    , 并可以运行
    c++ 中,函数的形参变量必须指定类型。没有形参建议写 void
    c语言代码
    #include
    //c 语言中形参可以没有数据类型 , 此时形参可以为任意类型
    //c++ 中形参必须有类型 , 没有形参建议写 void
    void fun(i)
    {
            printf("%d\n",i);
    }
    int main(int argc, char const *argv[])
    {
            fun(10);
            return 0;
    }

    5,更严格的类型转换

    C++ , 不同类型的变量之间赋值时,需要明确的类型转换。基本类型小转大除外
    C语言代码
    #include
    #include
    #include
    int main(int argc, char const *argv[])
    {
    // c 的方式自动转换
            int a = 65;
            char b = a;
            printf("%c\n",b);
    // C 中没有问题
            char *p = malloc(32);
            strcpy(p, "gl");
            return 0;
    }
    c++代码
    #include
    #include
    #include
    using namespace std;
    int main(int argc, char const *argv[])
    {
    // c 的方式自动转换
            int a = 65;
            char b = a;
            cout << "b=" << b << endl;
    // c++ 必须强转(明确数据类型) ,c 语言可以不用
            char *p = (char *)malloc(32);
            strcpy(p, "gl");
            cout << "p=" << p << endl;
            return 0;
    }

    6,struct类型加强

    1, C++ 中,定义结构体变量时,不用加 struct
    示例
    #include
    using namespace std;
    struct Stu
    {
            int id;
            char name[30];
    };
    int main(int argc, char const *argv[])
    {
            Stu s = {1, "gl"};
            cout << "id=" << s.id << ", name=" << s.name << endl;
            return 0;
    }
    2,struct 类型中可以有成员函数
    示例
    #include
    using namespace std;
    struct Stu
    {
            int id;
            char name[30];
            void eat()
            {
                    cout << name << "吃饭" << endl;
            }
    };
    int main(int argc, char const *argv[])
    {
            Stu s = {1, "gl"};
            s.eat();
            return 0;
    }

    7、新增bool 类型关键字

    标准 c++ bool 类型有两种内建的常量 true( 转换为整数 1) false( 转换为整数 0
    非标准 c++ bool 类型有两种内建的常量 true( 转换为非 0) false( 转换为整数 0
    1 字节
    示例
    #include
    using namespace std;
    int main(int argc, char const *argv[])
    {
            bool b1 = true;
            bool b2 = false;
            cout << "b1 = " << b1 << endl;
            cout << "b2 = " << b2 << endl;
            cout << "sizeof(bool) = " << sizeof(bool) << endl;
            return 0;
    }

    8,三目运算符功能增强

    C 中三目运算表达返回是变量的值, 而 c++ 中,三目运算表达式返回是变量
    示例
    int a=10,b=20;
    //c 编译失败
    //c++ 成功
    (a>b?a:b) = 100;
    cout << "a=" << a << " b=" << b << endl;

    9,const (重要)

    1,c 语言中 const 修饰的变量为只读变量
    #include
    int main(int argc, char *argv[])
    {
            const int num = 10;
            //c语言中使用 const 修饰变量为只读变量
            //此时无法通过变量名修改其值
            //num = 11;
            //但是可以通过指针变量修改值
            int *p = #
            *p = 11;
            printf("%d\n",num);
            return 0;
    }
    2,c++ const 修饰变量 如果以常量初始化该变量 不会立即开辟空间而是产生符号常量表 ,
    对其取地址会开辟新的内存地址
    #include
    using namespace std;
    int main(int argc, char *argv[])
    {
            const int num = 10;
            //此时 num 在符号常量表中 , 所以也无法通过变量名修改其值
            //num = 11;
            //当对该变量获取地址值 , 会为其开辟新的内存地址
            int *p = (int *)&num:
            *p = 11;
            cout << "num =" << num << endl;
            cout << "*p =" << *p << endl;
            return 0;
    }
    3, 如果以变量的形式初始化 const 变量 不会产生符号常量表 , 立即开辟空间
    #include
    using namespace std;
    int main(int argc, char *argv[])
    {
            int a = 10;
            const int num = a;
            int *p = (int *)#
            *p = 11;
            cout << "num =" << num << endl;
            cout << "*p =" << *p << endl;
            return 0;
    }
    4, 如果 const 修饰的是自定义类变量 , 立即开辟空间 , 不会产生符号常量表
    #include
    using namespace std;
    struct Stu
    {
            int age;
    };
    int main(int argc, char *argv[])
    {
            const Stu s = {18};
            //不可直接修改其中的内容
            //s.age = 19;
            Stu *p = (Stu *)&s;
            p->age = 20;
            cout << "p->age=" << p->age << endl;
            cout << "s.age=" << s.age << endl;
            return 0;
    }
    5,gcc 99/g++11 编译器中 const 修饰的变量可以作为数组创建时的长度 ,c 不行
            const int x = 10;
            int nums[x] = {0};
    6, 尽量使用 const 替代无参宏
            1,const 有类型,可进行编译器类型安全检查。 #define 无类型 , 不可进行类型检查
            2,const 有作用域,而 #define 不重视作用域。

    10,引用(重要)

    概念

    变量名实质上是一段连续内存空间的别名 , 通过变量来命名一片空间
    对一段连续的内存空间只能取一个别名吗?
    c++ 中新增了引用的概念,引用可以作为一个已定义的变量的别名。
    引用是 c++ c 的重要扩充 , 并不是 c++ 的发明。
    语法
            Type& ref = val;   
    注意
            1,&在此不是求地址运算,而是起标识作用。
            2,类型标识符是指目标变量的类型
            3,必须在声明引用变量时进行初始化。
            4,引用初始化之后不能改变。
            5,不能有 NULL 引用。必须确保引用是和一块合法的存储单元关联。
            6,可以建立对数组的引用。
    示例 1: 认识引用
     void test01(){
    int a = 10;
     //给变量 a 取一个别名 b
    int& b = a;
         
    cout << "a:" << a << endl;
    cout << "b:" << b << endl;
    cout << "------------" << endl;
    // 操作 b 就相当于操作 a 本身
    b = 100;
    cout << "a:" << a << endl;
    cout << "b:" << b << endl;
    cout << "------------" << endl;
    // 一个变量可以有 n 个别名
    int& c = a;
    c = 200;
    cout << "a:" << a << endl;
    cout << "b:" << b << endl;
    cout << "c:" << c << endl;
    cout << "------------" << endl;
    //a,b,c 的地址都是相同的
    cout << "a:" << &a << endl;
    cout << "b:" << &b << endl;
    cout << "c:" << &c << endl;
    }
    示例 2: 使用引用的注意事项
    void test02()
    {
    //1) 引用必须初始化
            int& ref; //报错 : 必须初始化引用
    //2) 引用一旦初始化,不能改变引用
            int a = 10;
            int b = 20;
            int& ref = a;
            ref = b; //不能改变引用
    //3) 不能对数组直接建立引用
            int arr[10];
            int& ref3[10] = arr;
    }
    示例 3: 建立数组引用
    void test03()
    {
    //1. 建立数组引用方法一
            typedef int ArrRef[10];
            int arr[10];
            ArrRef& aRef = arr;
            for (int i = 0; i < 10;i ++){
            aRef[i] = i+1;
    }
    for (int i = 0; i < 10;i++){
    cout << arr[i] << " ";
    }
    cout << endl;
    //2. 建立数组引用方法二(建议直接记第二种)
    int(&f)[10] = arr;
    for (int i = 0; i < 10; i++){
    f[i] = i+10;
    }
    for (int i = 0; i < 10; i++){
    cout << arr[i] << " ";
    }
    cout << endl;
    }
    示例 4: 建立指针变量的引用
    int num = 10;
    int *p = #
    int *&myP = p;
    cout<<"*myP = "<< *myP<< endl;
    示例 5: 给函数取别名
    void fun01(void)
    {
            cout << "fun01" << endl;
    }
    int main(void)
    {
            int (&p)(void) = fun01;
            p();
    }
    函数中的引用
    引用作为形参
            当函数中的形参是引用时, 是地址传递 , 类似与指针
            引用作为函数的参数优点:
            1、实参不用取地址
            2、引用(形参)不会另辟空间(不占空间)
            3、函数内部 不需要指针解引用
    示例:
    void test04(int& x)
    {
            x = 10;
    }
    int main(int argc, char *argv[])
    {
            int num = 1;
            test04(num);
            cout << "num=" << num << endl;
            return 0;
    }
    引用作为返回值
    当函数中的返回值为引用时 . 要确保当函数执行完毕后 , 引用关联的内存一定要存在
    示例 : 函数不要返回局部变量的引用
    int& test05()
    {
            static int x = 10;
            int& p = x;
            return p;
    }
    int main(int argc, char *argv[])
    {
            int& num = test05();
            cout << "num = " << num << endl;
            return 0;
    }
    示例 : 链式编程
    struct person
    {
             char name[50] = {0};
            person& eat = (person &p,char *foodname);
            {
                    cout << p.name << "吃" << foodname << endl;
                    return p;
            }
    };
    void  fun()
    {
            person *p = "zhangsan";
            p.eat(p,"油泼面").eat(p,"油泼面").eat(p,"油泼面“);        
    }
    常引用
    概述
            概念: 常量的引用
            特点: 值不能被修改
    示例
    void test07(void)
    {
    const int& num = 10;
    num = 11;//err 不能被修改
    }
    作用 : 防止函数内部 通过引用修改外部的值
    优点 :
            引用不产生新的变量,减少形参与实参传递时的开销。
            由于引用可能导致实参随形参改变而改变,将其定义为常量引用可以消除这种副作用。
            如果希望实参随着形参的改变而改变,那么使用一般的引用
            如果不希望实参随着形参改变,那么使用常引用
    void showData(const int &data)
    {
            //data = 2000;//err
            cout<<"data = "<
    }
    void test08()
    {
            int num = 100;
            showData(num);
            cout<<"num = "<
    }

    11,内联函数(了解)

    概念 : 由关键字 inline 修饰的函数 为内联函数。
    inline void add(int a,int b)
    {
            cout << a+b << endl;
    }
    int main()
    {
            //add(10,2);
            cout << 10+2 << endl;
    }
    特点:
            内联函数:在编译阶段像宏一样展开。有作用域的限制(作为类的成员函数)。
            内联函数为了继承宏函数的效率,没有函数调用时开销,然后又可以像普通函数那样,
            可以进行参数,返回值类型的安全检查,又可以作为成员函数。
    注意:
            1,inline只能在定义函数的时候修饰。
            2,任何在类内部定义的函数自动成为内联函数。
            3,inline修饰的函数是否为内联函数,取决于编译器。对于非 inline 修饰的函数,也

    有可能转成内联函数(体积小、功能简单的函数)。

    内联条件:

            不能存在任何形式的循环语句
            不能存在过多的条件判断语句
            函数体不能过于庞大
            不能对函数进行取址操作
    宏函数和内联函数区别(重要)面试题
    宏函数:
            参数没有类型, 不能保证参数的完整型。
            宏函数 在预处理阶段展开。
            宏函数 没有作用域限制 不能作为类的成员。
    内联函数:
            参数有类型 保证参数的完整型。
            内联函数 在编译阶段 展开。
            内联函数 有作用域限制 能作为类的成员
    示例:
    inline void test09(int a,int b)
    {
    cout << a+b << endl;
    }

    12,形参的默认值

    特点

            c++在声明函数原型的时可为一个或者多个参数指定默认 ( 缺省 ) 的参数值,当函数 调用
    的时候如果没有指定这个值,编译器会自动用默认值代替
    注意
            如果某形参设置了默认参数,那么这个形参的右方所有形参都必须设置默认参数 
    示例:
    void test10(int a = 1,int b = 10)
    {
            cout << "a = " << a << endl;
            cout << "b = " << b << endl;
    }
    int main(int argc, char *argv[])
    {
            test10();
            return 0;
    }
    1. void test10(int a=1,int b)//err
    2. {
    3. cout << "a = " << a << endl;
    4. cout << "b = " << b << endl;
    5. }
    6. int main(int argc, char *argv[])
    7. {
    8. test10(1);
    9. return 0;
    10. }

    13,占位参数

    概念

            只有形参类型 没有形参名的参数 叫占位参数。   
    示例
    void test11(int a,int)
    {
            cout << "a = " << a << endl;
    }
    void test12(int a,int=10)
    {
            cout << "a = " << a << endl;
    }
    int main(int argc, char *argv[])
    {
            test11(1,2);
            return 0;
    }
    注意
            占位参数 重载++ -- 运算符才用。

    14,函数重载

    函数重载 是静态多态。
    函数重载:一个函数名 多个函数功能。
    函数重载的条件:同一作用域,函数的参数个数、类型、顺序不同都可以重载,返回值类
    型不能作为重载条件。
    示例
         
    void test13()
    {
            cout << "test13-01" << endl;
    }
    void test13(int i)
    {
            cout << "test13-02" << endl;
    }
    void test13(int i,char c)
    {
            cout << "test13-02" << endl;
    }
    c++, 函数名和参数 一起决定函数的入口地址
    底层原理
    注意 :
    因为 c++ 在编译函数时会在函数名前随机添加新的名称所以此时 test13 函数将生成
    以下函数名
    _Z4test13v //v 代表无返回值
    _Z4test13i //i 为参数类型的首字母
    _Z4test13ic //i 为第一个参数类型的首字母 ,c 为第二个参数类型的首字母
    注意:
    // 函数重载和缺省参数 在一起 容易产生二义性
    void test14(int a)
    {
    cout << "test14-01" << endl;
    }
    void test14(int a,int b=10)
    {
    cout << "test14-01" << endl;
    }

    15,混合编程

    由于 c++ 可以使用 C 的模块中函数,当 C++ 整个工程编译时,可能会将使用 C 语言编写的函
    数名编译成 c++ 规则的函数名(定义的函数名前随机添加新的名称),链接程序时,可
    能会找不到目标函数,因此采用 extern "C" 解决。
    错误演示:
    //test.h
    #ifndef TEST_H
    #define TEST_H
    extern void test(int x);
    #endif // TEST_H
    //test.c
    void test(int x)
    {
    }
    //main.cpp
    #include
    #include "test.h"
    using namespace std;
    int main(int argc, char *argv[])
    {
            test();
            return 0;
    }
    修改
    //test.h
    #ifndef TEST_H
    #define TEST_H
    #ifdef __cplusplus
    extern "C"{
    #endif
    extern void test(int x);
    #ifdef __cplusplus
    }
    #endif
    #endif // TEST_H
  • 相关阅读:
    力扣记录:Hot100(5)——102-141
    基于vue+MySQL的毕业设计网上选题系统
    详解编码器和解码器电路:定义,工作原理,应用,真值表
    零基础自学SQL课程 | IF函数
    100003字,带你解密 双11、618电商大促场景下的系统架构体系
    HMM隐马尔可夫模型用于序列标注
    leetcode(力扣):203移除链表元素 leetcode(力扣):206反转链表 leetcode(力扣):876.链表的中间结点多种解法
    Vue3 组合式 API:依赖注入(四)
    同一公司开发的多个软件,可以用同一张代码签名证书吗?
    Django 里如何使用 sqlite (操作步骤)
  • 原文地址:https://blog.csdn.net/aisheisadas/article/details/134402793