当前位置: 首页 > news >正文

DAY02 c++对c的扩展

输出

语法     

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

输入

语法

        cin >> 变量名 1 >> 变量名 2 >> ...
示例
#include <iostream>
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 <iostream>
using namespace std;
int x = 100;
int main(int argc, char *argv[])
{
        int x = 1;
        cout << "x =" << x << endl;
        cout << "::x =" << ::x <<endl;
        return 0;
}

2,命名空间

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

示例

#include <iostream>
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 <iostream>
using namespace std;
int main(int argc, char *argv[])
{
        namespace A
         {
                int a = 10;
        }
        cout << A::a << endl;
        return 0;
}
// 此时报错
2, 命名空间嵌套命名空间 ( 命名空间中可以嵌套命名空间 )
#include <iostream>
using namespace std;
namespace A {
int a = 10;
        namespace B
        {
        int b = 20;
        }
}
int main(int argc, char *argv[])
{
        cout << "A::a" <<A::a << endl;
        cout << "A::B::b" << A::B::b << endl;
        return 0;
}
3, 命名空间的开放性(随时添加新的成员
#include <iostream>
using namespace std;
namespace A
{
        int a = 10;
}
namespace A {
        int a2 = 100;
}
int main(int argc, char *argv[])
{
        cout << "A::a" <<A::a << endl;
        cout << "A::a2" <<A::a2 << endl;
        return 0;
}
4, 无名命名空间
// 无名命名空间,意味着命名空间中的标识符只能在本文件内访问
#include <iostream>
using namespace std;
namespace {
        int a = 10;
}
int main(int argc, char *argv[])
{
        cout << "::a" <<::a << endl;
        return 0;
}
5, 取别名
#include <iostream>
using namespace std;
namespace XXX{
        int a = 10;
}
int main(int argc, char *argv[])
{
        namespace A = XXX;
        cout << "A::a" <<A::a << endl;
        return 0;
}
using 关键字
作用 1:using 声明命名空间中的具体成员
#include <iostream>
using namespace std;
namespace A{
        int a = 10;
        int b = 1;
}
int main(int argc, char *argv[])
{
        //声明命名空间 A 中的 a 变量
        using A::a;
        //使用时可以省略空间名 ::
        cout << "a=" <<a << endl;
        cout << "A::b=" << A::b << endl;
        return 0;
}
注意 : 容易造成同范围内的命名冲突
#include <iostream>
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=" <<a << endl;
        cout << "A::b=" << A::b << endl;
        return 0;
}
作用 2:using 声明成员函数 遇到函数重载
#include <iostream>
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 <iostream>
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 <iostream>
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 <stdio.h>
//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 <stdio.h>
#include <stdlib.h>
#include <string.h>
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 <iostream>
#include <cstdlib>
#include <cstring>
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 <iostream>
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 <iostream>
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 <iostream>
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 <stdio.h>
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 <iostream>
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 <iostream>
using namespace std;
int main(int argc, char *argv[])
{
        int a = 10;
        const int num = a;
        int *p = (int *)&num;
        *p = 11;
        cout << "num =" << num << endl;
        cout << "*p =" << *p << endl;
        return 0;
}
4, 如果 const 修饰的是自定义类变量 , 立即开辟空间 , 不会产生符号常量表
#include <iostream>
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 = &num;
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 = "<<data<<endl;
}
void test08()
{
        int num = 100;
        showData(num);
        cout<<"num = "<<num<<endl;
}

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;
}
void test10(int a=1,int b)//err
{
cout << "a = " << a << endl;
cout << "b = " << b << endl;
}
int main(int argc, char *argv[])
{
test10(1);
return 0;
}

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 <iostream>
#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

相关文章:

  • 二维码在区域巡查中的应用:隐患上报、巡逻巡更、管线巡查
  • 数据结构--图解单链表
  • 响应系统的作用与实现
  • 攻防世界-web-unseping
  • 如何设计短域名系统
  • V-for中 key 值的作用,如何选择key
  • 《洛谷深入浅出进阶篇》P3397 地毯————二维差分
  • 部署百川大语言模型Baichuan2
  • 经验篇:大数据常用工具集合
  • k8s之HPA
  • 解锁内存之谜:从C到Python、Java和Go的内存管理对比
  • 基于安卓android微信小程序的装修家装小程序
  • pycharm使用
  • requests 在 Python 3.2 中使用 OAuth 导入失败的问题与解决方案
  • Axure9 基本操作(二)
  • @jsonView过滤属性
  • [译]Python中的类属性与实例属性的区别
  • 【Under-the-hood-ReactJS-Part0】React源码解读
  • 【跃迁之路】【585天】程序员高效学习方法论探索系列(实验阶段342-2018.09.13)...
  • 〔开发系列〕一次关于小程序开发的深度总结
  • 10个确保微服务与容器安全的最佳实践
  • Angularjs之国际化
  • C++类中的特殊成员函数
  • C语言笔记(第一章:C语言编程)
  • Hibernate最全面试题
  • leetcode388. Longest Absolute File Path
  • SpringCloud(第 039 篇)链接Mysql数据库,通过JpaRepository编写数据库访问
  • Spring技术内幕笔记(2):Spring MVC 与 Web
  • vue数据传递--我有特殊的实现技巧
  • 分享一个自己写的基于canvas的原生js图片爆炸插件
  • 微信支付JSAPI,实测!终极方案
  • 协程
  • 写给高年级小学生看的《Bash 指南》
  • 要让cordova项目适配iphoneX + ios11.4,总共要几步?三步
  • 一起来学SpringBoot | 第十篇:使用Spring Cache集成Redis
  • 数据库巡检项
  • ​【已解决】npm install​卡主不动的情况
  • ​插件化DPI在商用WIFI中的价值
  • ​软考-高级-系统架构设计师教程(清华第2版)【第9章 软件可靠性基础知识(P320~344)-思维导图】​
  • #我与Java虚拟机的故事#连载15:完整阅读的第一本技术书籍
  • (1)(1.13) SiK无线电高级配置(五)
  • (23)Linux的软硬连接
  • (LeetCode) T14. Longest Common Prefix
  • (附源码)spring boot基于Java的电影院售票与管理系统毕业设计 011449
  • (十八)用JAVA编写MP3解码器——迷你播放器
  • (四)docker:为mysql和java jar运行环境创建同一网络,容器互联
  • (推荐)叮当——中文语音对话机器人
  • (已解决)vue+element-ui实现个人中心,仿照原神
  • (转)GCC在C语言中内嵌汇编 asm __volatile__
  • (轉貼)《OOD启思录》:61条面向对象设计的经验原则 (OO)
  • **PHP分步表单提交思路(分页表单提交)
  • .NET Core 和 .NET Framework 中的 MEF2
  • .NET Framework 和 .NET Core 在默认情况下垃圾回收(GC)机制的不同(局部变量部分)
  • .Net IOC框架入门之一 Unity
  • ?.的用法