美文网首页
C++ 语法笔记

C++ 语法笔记

作者: 重案组之虎曹达华_ | 来源:发表于2021-06-09 17:16 被阅读0次

    最近需要用C++做一些跨平台的组件,我自己本身对C++的语法不是特别熟练,也算是边写边学。
    记录了一些平时开发过程中用到的语法笔记。

    1.C++支持函数重载,C不支持。底层用了namemangling技术,通过编译器把函数名字改掉,每个方法名不一样。不同编译器有不同的生成规则。

    2.extern "C":

    • 被extern "C" 修饰的代码会按照C语言的方式去编译。

      extern "C" {
            void fun(){
            count << "func()" << endl;
          }
      }
      
    • 如果函数同时有声明和实现,要让函数声明被extern "C" 修饰,函数的实现可以不修饰。

    • 假如有两个函数是通过.c(C语言)的方式进行实现的,那么在cpp的文件中,假如想使用这两个函数的话,不仅要声明,并且需要的在声明外要用 extern "C" 修饰。告诉编译器,这两个方法是用C语言来实现的。

    • 当然也可以这么写

      extern "C" {
            #include "math.h"//include的作用:把math.h的内容原封不动的拷贝一份。
      }
      
    • 那么一个函数声明既要给C调用又要给C++调用怎么办呢?用__cplusplus宏来判断你是否在C++的环境

      #ifdef __cplusplus
      extern "C" {
      #endif
        
        //这里是是你的声明或者代码,xxx
        
      #ifdef __cplusplus 
      }
      #endif
      

    3.防止重复include:

    • 基于include只是执行了copy操作,所以include多次在语法上都没啥问题,但是代码量会增多,因此为了防止多次include

      可以用以下代码:首次未定义才进入声明逻辑。

    #ifndef ABC
    #define ABC
    
    xxx
    
    • 或者可以用编译器的特性#pragma once来指名头文件只包含一次。

    两者区别:第一种不受编译器的任何限制,是标准语法。第二种老编译器不支持,兼容性不够,只针对整个文件。

    4.inline内联函数:本质把方法替换成具体实现,可以减少函数调用的开销,会增大代码体积会。但inline只是仅仅是建议编译器进行替换,有时候声明了也不一定起作用,比如:递归。递归是无法内联的。

    内敛函数和宏都可以减少函数的开销,对比宏,内敛函数有函数的特性,有代码提示。

    5.const:被修饰的变量不可修改

    如果修饰的是类或者结构体,那么其中的成员也不可更改。

    const修饰右边的东西

    int age = 10;
    int height = 20;
    
    int *p = &age; //int * 是一个int指针 p是具体的值
    *p = 20; //修改p指向的具体值
    p = &height;  //修改p的值
    
    const int *p1 = &age;// p1是常量,*p1是常量,所以不能改年龄
    int const *p2 = &age;// 和p1没区别
    int * const p3 = &age;//p3是常量,*p3不是,因此可以年龄。
    const int * const p4 = &age;//两个都不能改
    int const * const p5 = &age;//两个都不能改
     
    

    6.引用

    在C++ 中,引用可以起到跟指针类似的功能,但指针可以修改,引用必须初始化,一旦指向了某个变量,就不可以再改变。

    int age = 10
    int &refAge = age;
    age = 20;
    

    价值:比指针更安全。因为指针在中途可以修改指向,引用不能。

    本质:引用是弱化了的指针。本质是指针

    7.this

    通常一个对象的成员变量是在对象当中的,而函数是放在代码段的,为了在函数体内用this能访问到对象本身,这里有个一个隐式参数,把对象地址传入函数体中,然后将对象地址给this进行赋值

    8.堆的申请和释放

    new和delete或者new[]和delete[]必须成对出现

    char *p = new char[4]; //申请连续的4个字节、*p指向第一个。char类型的数组
    *p = "11";//给第一个字节赋值
    *(p + 1) = "12"//给第二个字节赋值
    delete[] p;
    
    memset(p,1,4);//p的4个字节每一个字节都是1
    
    

    9.析构函数

    对象销毁时,进行调用,通过malloc分配的对象free时不会调用析构函数,声明为pulic才能被外界正常使用。

    构造方法的顺序和析构的顺序相反。

    构造函数: 父类构造->子类构造

    析构函数: 子类析构->父类析构

    10.多态

    定义:同一操作作用于不同的对象,可以有不同的解释,产生不同的执行结果。

    方法的调用,默认看指针类型进行操作,不看实际的对象类型是什么。

    很多语言默认支持多态,C++要实现多态,需要用到虚函数。

    11.虚函数

    定义:被virtual修饰的成员函数

    只要在父类中声明为虚函数,子类中重写的函数也自动变成虚函数(子类可以省略virtual关键字)

    1.有虚函数存在一个类顶部会多4个字节,这个4个字节存放的是虚表(虚函数表)的地址,虚表里面有每个虚函数的方法地址。

    2.所有对象共用一张虚表。(如果是多继承就多张虚表)

    3.因此如果父类指针指向子类对象,析构函数也应该定义为虚函数。否则释放时无法调用子类的虚函数。

    12.模版

    模版的本质类似范型,编译器会为多类型的入参生成多个类型的函数。

    13.类型转换

    static_cast:普通转换,不支持交叉转换。

    dynamic_cast:支持交叉转换,会做安全计算。

    reinterpret_cast:简简单单的二进制复制。

    const_cast:把const转换成非const。

    14.nullptr可以解决NULL的二义性(既代表0又代表空指针)

    15.智能指针

    传统指针存在的问题:

    1.需要手动管理内存。

    2.容易发生内存泄漏。

    3.释放之后产生野指针。

    智能指针可以解决这些问题。

    实现原理类似于装箱和拆箱,用一个内部私有指针保存对象。在释放时,自动释放私有的内部指针。

    相关文章

      网友评论

          本文标题:C++ 语法笔记

          本文链接:https://www.haomeiwen.com/subject/roweeltx.html