一、 内联函数(inline)

宏函数(带参数的宏)出现的问题

  1. 在c中也会出现,宏看起来像一个函数调用,但是会有隐藏一些难以发现的错误;
  2. C++ 特有的,预处理器不允许访问类的成员,也就是说预处理器宏不能作类的成员函数

内联函数

内联函数为了继承宏函数的效率,没有函数调用时的开销,然后又可以像普通函数那样,可以进行参数、返回值类型的安全检查,又可以作为成员函数。

内联函数是一个真正的函数。

内联函数会在适当的地方像宏一样展开。 发生在编译阶段。

在函数定义处使用 inline

以空间换时间。

在类内部定义的函数自动成为内联函数!

条件:

  1. 不能存在任何形式的循环语句
  2. 不能存在过多的条件判断语句
  3. 函数体不能过于庞大不能对函数进行取址操作

内联函数仅仅是对编译器的建议。

二、函数的默认参数

C++ 在声明函数原型时可为一个或多个参数指定默认(缺省)的参数值,当函数调用的时候如果没有指定这个值(传递该参数),编译器会自动用默认值代替。

默认参数从左往右。

  1. 函数的默认参数从左往右,如果一个参数设置了默认参数,那么这个参数之后的参数都必须设置默认参数。
  2. 如果函数声明和函数定义分开写,函数声明和函数定义不能同时设置默认参数。
  3. 推荐函数声明处写默认参数(缺省函数)。因为在分文件的情况下,是声明处的默认参数起效果。

函数的占位参数

函数的参数只有类型名,没有形参名,这个参数就是占位参数。

由于有类型名,所以函数调用的时候必须给占位参数传参。

由于没有形参名,所以函数内部是无法使用占位参数。

void func(int x, int y, int) {
    cout << "x = " << x << ", y = " << y << endl;
    return;
}

func(1, 2, 3); // 必须传参,但是内部不能使用该参数

// 操作符重载的后置++要用这个

三、函数重载(overload)

(多态的体现)

定义

同一个函数名在不同场景下可以具有不同的含义。

意义

方便使用函数名

条件

  1. 同一作用域
  2. 参数个数不同
  3. 参数类型不同
  4. 参数顺序不同

注意

  1. 函数返回值不能作为函数重载的依据

    在编写程序的过程中可以忽略他的返回值,所以编译器不将返回值当成依据。

四、C和C++混合编程

// fun.h
#ifndef FUNC_H
#define FUNC_H

#if __cplusplus
extern "C" {
#endif

extern int my_add(int x, int y);
extern int my_sub(int x, int y);

#if __cplusplus
}
#endif

#endif // FUNC_H

// func.c
#include <stdio.h>

int my_add(int x, int y) {
    return x + y;
}

int my_sub(int x, int y) {
    return x - y;
}

// main.cc
#include <iostream>

#include "func.h"

using namespace std;

int main()
{
    cout << "Hello World!" << endl;
    cout << my_add(100, 200) << endl;
    cout << my_sub(100, 200) << endl;
    return 0;
}

IDE 可以自动识别混合的代码,分别使用不同的编译器编译。手动需要先编译C程序再链接两者:

gcc -c func.c -o func.o
g++ main.cc func.o -o main

五、类

C 语言 数据是数据 方法是方法 。

出现一个问题 (数据 方法独立 容易造成 方法 调用错误

C 语言 的结构体

在C语言中,行为和属性是分开的,也就是说吃饭这个属性不属于某个类对象,而属于所有共同数据,所以不单单是 PeopleEat 可以调用 Person 数据, AnimalEat 也可以调用 Person 数据,万一调用错误,将会导致问题发生。

由此,属性和方法应该放在一起,一起表示一个具有属性和行为的对象。

封装

  1. 把变量(属性)和函数(操作)合成一个整体,封装在一个类中;
  2. 对变量和函数进行访问控制

访问权限

  1. 在类的内部(作用域范围内),没有访问权限之分,所有成员可以相互访问
  2. 在类的外部(作用域范围内),访问权限才有意义: public , private , protected
  3. 在类的外部,只有 public 修饰的成员才能被访问,在没有涉及继承与派生时,privateprotected 是同等级的,外部不允许访问。
访问属性 属性 对象内部 对象外部
public 公有 可访问 可访问
protected 保护 可访问 不可访问
private 私有 可访问 不可访问

类的格式

class 类名 { // 抽象的概念 系统不会为其分配空间
    private: // 私有 类的外部 不可直接访问
    protected: // 保护 类的外部  不可直接访问
    public: // 公有 类的外部 可以直接访问

    // 在类的内部没有权限之分 都可以相互访问
}

用类去实例化一个对象。

将成员变量设置为 private

  1. 可赋予客户端访问数据的一致性。如果成员变量不是 public ,客户端唯一能够访问对象的方法就是通过成员函数。如果类中所有的 public 权限的成员都是函数,客户在访问类成员时只会默认访问函数,不需要考虑访问成员需不需要添加(),省下不少时间
  2. 可细微划分访问控制。使用成员函数可使得我们对变量的控制处理更加精细。如果我们让所有成员变量为 public ,每个人都可以读写它。如果我们设置为 private ,我们可以实现“不准访问”、“只读访问”、“读写访问”,甚至“只写访问”