C++ 学习笔记(三)—— 入门+类和对象

1、内联函数(inline)

内联函数主要是解决C语言的宏的缺陷提出来的;

宏的缺陷:

1)容易出错,语法坑很多;

2)不能调试;

3)没有类型安全的检查;

宏的优点:

1)没有类型的严格限制;

2)针对频繁调用小函数,不需要再建立栈帧,提高了效率;

cpp 复制代码
// 内联函数的使用示例
inline int add(int x, int y)
{
    return x + y;
}

int main()
{
    add(1, 2);  // 在debug模式下不会展开,方便调试;
    // 但是在release版本下可以展开;
    // 不像宏一样只是单纯的替换,减少了语法坑;
    // 内联函数虽然有诸多好处,但是容易导致目标文件过大,因此一般只将很小的函数设为内联;
    // 有一些编译器会自动识别,过大和递归的函数设置为内联会被编译器忽略;

    // 内联函数不能声明和定义分离;
    // 因为内联是在汇编的时候就已经要展开了,如果声明和定义分离就要在机器语言链接的时候才能关联;
    // 链接的符号表里内联函数不会存在,编译器也默认在之前就已经展开了;
    // 因此会报链接错误;
}
2、C++11语法糖
1)auto

根据等式右边的值自动推导左边的值的类型;该方案在常规情况下价值比较低,只有在类型名字很长的时候才能体现它的价值;

比如:std:: vector<std::string>::iterator oo = v.begin(); ------>auto oo = v.begin();

但需要注意auto不能作为函数的参数也不能用来声明数组;

小扩展:

如果用着用着不记得类型是啥了,可以通过typeid(变量).name()返回类型字符串;

2)范围for
cpp 复制代码
int main()
{
    int array[] = {1, 2, 3, 4, 5};
    // 传统遍历数组的方法
    for(int i = 0; i < sizeof(array) / sizeof(array[0]); ++i)
        cout<< array[i] << " ";
    cout << endl;
    // 范围for用法
    // 这里是把array里的值赋值给e哦,所以改变e是不会改变array里面的值的;
    for(auto e : array)  // 这里不是非得用auto,用int也可以,只是auto比较通用比较方便
    {
        cout << e << " ";
    }
    cout << endl;
        return 0;
}

void func(int array[])
{
    // 此处会报错哦,因为此处array看起来是数组,其实是指针啦,范围for不支持;
    for(auto e : array)  
    cout << e << endl;
}
3)空指针nullptr

NULL实际是一个宏,在传统的C头文件(stddef.h)中,可以看到:

#define NULL 0 (C++自己定义的,C语言没有)

因此在有些地方,会被识别为字面常量0,也容易导致一些错误的出现,如:

cpp 复制代码
void func(int p)
{
    cout << "int" << endl;
}

void func(int* p)
{
    cout << "int*" << endl;
}

func(NULL);  // 此处会显示"int"而不是"int*"
//为了解决这种错误,引入nullptr代表空指针;
3、 类和对象

之前有说过,在C++中兼容的结构体,本质上已经升级为了类,但是纯正的类,更喜欢用class作为定义类的关键字;而且,struct和class还是有一定的区别的,主要就是在访问限定符的使用上。

1)访问限定符

访问限定符:public(公有)、protected(保护)、private(私有)【目前暂时可以将保护和私有看作是一样的】------公有在类的外面可以访问,保护和私有只能在类里面访问;

cpp 复制代码
class Stack
{
// 成员函数
void Init()
{
    a =nullptr;
    top = capacity = 0;
}

void Push(int x)
{
// 扩容判断
    if(top = capacity)
    {
        size_t newcapacity = capacity == 0 ?4 : capacity * 2;
        a = (int* )realloc(a, sizeof(int)*newcapacity);
        capacity = newcapacity;
    }

    // 插值
    a[top++] = x;
}

    // 成员变量
    int* a;
    int top;
    int capacity;
}

int main()
{
    Stack ss;
    ss.Init();
    ss.Push(1);  // 此处都会报错哦,error:访问私有数据;
    //  修改的方法,要不然把class改成struct,要不然就在需要外部访问的成员前加"public:"修饰;
    //  访问限定符的修饰范围是从访问限定符开始到下一个访问限定符/结束;
    //  class的默认访问限定是私有的哦,所以没有加public都是私有的都不能访问哦~
    //  访问限定符只限制类外访问,类中访问无限制;
    return 0;
}

// 类也可以声明和定义分离
// test.h
class Stack
{
public:
    // 成员函数
    void Init();
    void Push(int x);
private:
    // 成员变量
    int* a;
    int top;
    int capacity;
}

//  test.cpp
void Stack::Init()
{
    a =nullptr;
    top = capacity = 0;
}

void Stack::Push(int x)
{
    // 扩容判断
    if(top = capacity)
    {
        size_t newcapacity = capacity == 0 ?4 : capacity * 2;
        a = (int* )realloc(a, sizeof(int)*newcapacity);
        capacity = newcapacity;
    }
    // 插值
    a[top++] = x;
}

小扩展:
1)之前有提到过,一个语句如果要用一个函数或者一个变量,都是去之前的也就是上面的语句中查找,如果需要用到的函数或者变量在这个语句之后定义,就会出现找不到的情况,这种的话需要提前写一个声明才可以。
但是类里面的话,我们一般习惯把成员函数写在上面,成员变量写在下面,这种写法却不会出现找不到的情况,因为类是一个整体,所以里面的变量和函数无关顺序;
2)还需要注意,在类里面定义的成员函数默认就是内联函数,这一点后面会具体说;
3)成员的命名习惯:为了避免引用参数和成员变量同名导致错误的产生,比如时间类:

cpp 复制代码
class Date
{
public:
    void Init(int year, int month, int day)
    {
    year = year;  //  此处虽然不会报错,但是也并不会被正确的初始化,因为局部优先,会变成参数自己赋            值给自己,而不会赋值给成员变量
    //  因此,成员变量一般命名为"_year"、"year_";该方法虽然不是必须的,但是是约定俗成的;
    }
private:
    int year;
    int month;
    int day;
}
2)类的作用域

类定义了一个新的作用域,类的所有成员都在类的作用域中。在类外定义成员时,需要使用::作用域操作符指明成员属于哪个类域;------ 这个在声明和定义分开的部分已经举过例子了;

cpp 复制代码
// 以下脑洞大开的用法
class Date
{
public:
    void Init(int year, int month, int day)
    {
        _year = year;
        _month = month;
        _day = day;
    }
private:
    int _year;
    int _month;
    int _day;
}

int main()
{
    Date::_year;
    Date._year;  //  都是非法语句哈
    //  因为类里面的成员变量设置的地方只是一个声明,不是定义;
    //  无法访问一个声明里面的变量;
}
3)类的实例化
相关推荐
我爱挣钱我也要早睡!32 分钟前
Java 复习笔记
java·开发语言·笔记
知识分享小能手3 小时前
React学习教程,从入门到精通, React 属性(Props)语法知识点与案例详解(14)
前端·javascript·vue.js·学习·react.js·vue·react
汇能感知5 小时前
摄像头模块在运动相机中的特殊应用
经验分享·笔记·科技
阿巴Jun6 小时前
【数学】线性代数知识点总结
笔记·线性代数·矩阵
茯苓gao6 小时前
STM32G4 速度环开环,电流环闭环 IF模式建模
笔记·stm32·单片机·嵌入式硬件·学习
是誰萆微了承諾6 小时前
【golang学习笔记 gin 】1.2 redis 的使用
笔记·学习·golang
利刃大大6 小时前
【高并发内存池】五、页缓存的设计
c++·缓存·项目·内存池
DKPT7 小时前
Java内存区域与内存溢出
java·开发语言·jvm·笔记·学习
aaaweiaaaaaa7 小时前
HTML和CSS学习
前端·css·学习·html
ST.J7 小时前
前端笔记2025
前端·javascript·css·vue.js·笔记