C++基础

作者: 来金德瑞 | 来源:发表于2021-02-09 16:06 被阅读0次

    基础知识

    • C++的源文件扩展名是:cpp(c plus plus)
    • C++程序的入口是main函数(函数既方法,一个意思)
    • C++完全兼容C语言的语法,很久之前,C++叫做C with classes

    发展历史

    截屏2021-02-09 下午1.57.33.png

    cin、cout

    • C++中常使用cin、cout进行控制台的输入和输出
    • cin用的是右移运算符 >> ,count用的是左移运算符 <<
    • endl 是换行运算符
    #include <iostream>
    using namespace std;
    int main(int argc, const char * argv[]) {
        int age;
        cin >> age;
        cout << "age is " << age << endl;
        return 0;
    }
    

    函数重载(Overload)

    • 规则
      • 函数名相同
      • 参数个数、参数顺序、参数类型不同
    • 注意
      • 返回值类型函数重载无关
      • 调用函数时,实参的隐式类型类型转换可能会产生二义性
    • 本质
      • 采用了name mangling或者叫name decoration技术
        • C++编译器默认会对符号名(变量名、函数名等)进行改编、修饰,有些地方翻译为“命名倾轧”
        • 重载时会产生多个不同的函数名,不同编译器(MSVC、g++)有不同的生成规则
        • 用过IDA打开【VS_Release_禁止优化】可以看到
    #include <iostream>
    using namespace std;
    
    
    // display_v
    void display() {
        cout << "display() " << endl;
    }
    
    // display_i
    void display(int a) {
        cout << "display(int a) " << a << endl;
    }
    
    // display_l
    void display(long a) {
        cout << "display(long a) " << a << endl;
    }
    
    // display_d
    void display(double a) {
        cout << "display(double a) " << a << endl;
    }
    
    int main(int argc, const char * argv[]) {
        display();
        display(10);
        display(10l);
        display(10.1);
        return 0;
    }
    

    extern "C"

    • 被extern "C" 修饰的代码会按照C语言的方式去编译
    extern "C" void func() {
        cout << "func" << endl;
    }
    
    
    extern "C" void func2(int age) {
        cout << "func(int age)" << age << endl;
    }
    
    
    extern "C" {
        void func3(){
            cout << "func()" << endl;
        }
    
        void func4(int age) {
            cout << "func(int age)" << age << endl;
        }
    }
    
    • 如果函数同时有声明和实现,要让函数声明extern “C” 修饰,函数实现不可以修饰
    extern "C" void func();
    extern "C" void func2(int a);
    
    extern "C" {
        void func3();
        void func4(int a);
    }
    
    void func() {
        cout << "func()" << endl;
    }
    
    void func2(int a) {
        cout << "func(int a) " << a << endl;
    }
    
    • 由于C、C++编译器规则的不同,在C、C++混合开发时候,可能会出现以下操作
      • C++在调用C语言API的时候,需要使用extern "C" 修饰C语言的函数声明
    • 有时候也会在编写C语言代码中直接使用extern "C",这样可以直接被C++调用
    • 通过使用宏__cplusplus来区分C、C++环境
    // sum.h
    
    #ifndef __SUM_H
    #define __SUM_H
    
    #ifdef __cplusplus
    extern "C" {
    #endif // __cplusplus
    
    int sum(int a, int b);
    int minus(int a, int b);
    
    #ifdef __cplusplus
    }
    #endif // __cplusplus
    
    #endif // !__SUM_H
    
    // sum.c
    
    #include "sum.h"
    
    // _sum
    int sum(int a, int b) {
        return a + b;
    }
    
    int minus(int a, int b) {
        return a - b;
    }
    
    // main.cpp
    #include <iostream>
    #include "sum.h"
    using namespace std;
    int main(int argc, const char * argv[]) {
        cout << sum(10, 20) << endl;
        return 0;
    }
    

    默认参数

    • C++ 允许函数设置默认参数,在调用时可以根据情况省略实参,规则如下:
      • 默认参数只能按照右到左的顺序
      • 如果函数同时有声明、实现,默认参数只能放在函数声明中
      • 默认参数的值可以是常量、全局符号(全局变量、函数名)
    #include <iostream>
    using namespace std;
    
    int age = 33;
    
    void test() {
        cout <<  "test()" << endl;
    }
    
    void display(int a = 11, int b = 22, int c = age, void (*func)() = test) {
        cout << "a is " << a << endl;
        cout << "b is " << b << endl;
        cout << "c is " << c << endl;
        func();
    }
    
    int main(int argc, const char * argv[]) {
        display();
        return 0;
    }
    
    • 函数重载、默认参数可能会产生冲突、二义性(建议优先选择默认参数)
    #include <iostream>
    using namespace std;
    
    void display(int a, int b = 20) {
        cout << "a is" << a << endl;
    }
    
    void display(int a) {
        cout << "a is" << a << endl;
    }
    
    int main(int argc, const char * argv[]) {
        // Call to 'display' is ambiguous
        display(10);
        return 0;
    }
    

    内联函数

    • 使用inline修饰函数的声明或者实现,可以使其变成内联函数
      • 建议声明和实现都增加inline修饰
    • 特点
      • 编译器会将函数调用直接展开为函数体代码
      • 可以减少函数调用的开销
      • 会增大代码体积
    • 注意
      • 尽量不要内联超过10行代码的函数
      • 有些函数即使声明为inline,也不一定会被编译器内联,比如递归函数。
    #include <iostream>
    using namespace std;
    
    inline int sum(int a, int b);
    
    int main() {
        sum(10, 20);
    
        getchar();
        return 0;
    }
    
    inline int sum(int a, int b) {
        return a + b;
    }
    

    内联函数与宏

    • 内联函数与宏,都可以减少函数调用的开销
    • 对比宏,内联函数多了语法检测和函数特性

    #pragma once

    • 我们经常使用#ifndef#define#endif来防止头文件内容被重复包含
    • #pragma once可以防止整个文件的内容被重复包含
    • 区别
      • #ifndef#define#endif 受C\C++标准的支持,不受编译器的任何限制
      • 有些编译器不支持#pragma once(较老编译器不支持,如GCC 3.4版本之前的),兼容性不够好
      • #ifndef#define#endif 可以针对一个文件中的部分代码,而#pragma once只能针对整个文件

    相关文章

      网友评论

          本文标题:C++基础

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