03 函数

  • 一、 使用具有默认参数的函数

    • 不可以靠左边缺省
    • 只能给出一次缺省值
    • 声明时给出了缺省值,定义时不能重复给出
  • 二、 内联函数

    • 实质是用目标程序的长度来换取执行时间。程序代码占用多份空间,但免去调用的额外开销。
    • 一般把规模很小但频繁调用的函数声明成内联
    • 使用inline,只是请求编译器内联该函数,是否内联由编译器决定
  • 三、 变量的作用域

    • 在C++中,变量作用域可以分为三类(C语言中,作用域包括前两类):
      • 块作用域(函数作用域):局部变量
      • 文件作用域:全局变量
      • 类的作用域:全局变量,C++专属,本章不涉及
    • 全局变量与局部变量同名时,局部变量优先。可以利用域作用符::区分两者
  • 四、 变量的生命周期

    • 储存类别
      • 1.程序代码区—存放函数体的二进制代码(忽略)
      • 2.静态区(static):一旦分配,直到程序结束才回收(终 生不死);全局变量,静态局部变量
      • 3.栈(Stack):存储函数参数和局部变量,空间由系统自动动态分配,回收。函数被调用,分配,压栈;执行完, 回收,弹出。特点:空间小(xMB量级),速度快
      • 4.堆(Heap):程序员动态申请的内存块,new申请, delete释放(Java自动释放)。特点:空间大(xGB量 级),速度慢。对于C/C++,如果程序员忘记回收,终 生不死,直到操作系统关闭。
    • 变量--->储存类别
      • 全局变量--->静态区
      • 静态局部变量--->静态区
      • 缺省局部变量-->动态区
      • 寄存器变量--->在cpu内部储存
  • 五、 全局变量的存储方式(extern,static)

    • 用static声明静态变量
      • static局部变量:存储在静态存储区,在函数内部定义,只限在函数内部使用
      • static全局变量:存储在静态存储区,在函数外部定义,只限在本文件中使用
      • extern全局变量:存储在静态存储区,在其他文件中定义,在本文件中可以使用
  • 六、 内部函数外部函数

    • 内部函数:函数只局限于在本文件中调用,其它文件不能调用,用static定义该函数。
    • 外部函数:函数的默认形式。
      • 在调用文件中用extern 声明,把该函数的作用域扩展到调用文件。

06 类和对象的使用

  • 一、 构造函数
class A {
    float x, y, z;
public:
    A(float a, float b = 10) {
        x = a;
        y = b;
        z = 0;
    }

    A(float a, float b, float c) : x(a), y(b), z(c) {
    }

    A() = default;
};
  • 二、 析构函数
    在对象的生命期结束时,系统自动调用析构函数,收回为对象分配的存储空间。 作用与构造函数正好相反。
~A() {
    cout << "这个对象被析构了";
}
  • 三、 复制构造函数
class Str {
    int length;
    char *sp;
public:
    Str(char *str) {
        if (str) {
            length = strlen(str);
            sp = new char[length + 1];
            strcpy(sp, str);
        } else sp = 0;
    }

    void show() { cout << sp << endl; }

    Str(const Str &s);

    ~Str() {
        if (sp) delete[]sp;
    }
};

//浅拷贝
//Str::Str(const Str &s) {//隐含的复制构造函数
//    length = s.length;
//    sp = s.sp;
//}


//深拷贝
Str::Str(const Str &s) {
    if (s.sp) {
        length = s.length;
        sp = new char[s.length + 1];
        strcpy(sp, s.sp);
    } else {
        sp = 0;
    }
}
  • 四、 赋值运算符(重载)函数
#include <iostream>

using namespace std;

class Stu {
    int age;
public:
    Stu() {}

    Stu(int age) : age(age) {}

    int operator+(const Stu &s) {
        return age + s.age;
    }

    friend ostream &operator<<(ostream &output, Stu &s) {
        output << "年龄: " << s.age;
        return output;
    }

    friend istream &operator>>(istream &input, Stu &s) {
        input >> s.age;
        return input;
    }


};

int main() {
    Stu s1(14), s2;
    cin >> s2;
    cout << s1 + s2 << endl;
    cout << s2;
}


08 继承和派生

继承的概念-派生类的构造函数和析构函数

  • 派生类构造函数
    • 首先调用基类的构造函数来初始化基类成员和子对象
    • 然后对其中包含的对象以及成员变量初始化
    • 最后调用自身构造函数
  • 派生类构造函数名(总参数表列): 基类构造函数名(参数表列) ,子对象名(参数表列) { 派生类中新增数据成员初始化语句 }
  • 在派生类对象释放时,顺序相反。
class A {
    int name;
public:
    A(int n) : name(n) {
        cout << "A_" << name << "构造了"<<endl;
    }

    ~A() {
        cout << "A_" << name << "析构了"<<endl;
    }
};

class B : public A {
    int age;
    int n;
    A a;
public:
    B(int g, int n) : age(g), a(22), A(n) {
        cout << "B_" << age << "构造了"<<endl;
    }

    ~B() {
        cout << "B_" << age << "析构了"<<endl;
    }
};

int main() {
    B b(1, 1);
}
A_1构造了
A_22构造了
B_1构造了
B_1析构了
A_22析构了
A_1析构了

多重继承

  • 调用基类构造函数的顺序:按照声明派生类时基类出现的顺序

  • 二义性,需使用virtual

class A {
public:
    int x;
    A(int a = 0) { x = a; }
};

class B : virtual public A {
public:
    B(int a) : A(a) {}
};

class C : virtual public A {
public:
    C(int a) : A(a) {}
};

class D : public B, public C {
public:
    D(int a, int b, int c) : B(b), C(c), A(a) {}
};

int main() {
    D d(1, 2, 3);
    cout << d.x << endl;
}

多态

  • 编译时的多态性,静态多态(函数重载、运算符重载)
  • 运行时的多态性,动态多态(虚函数)
class A {
public:
    virtual void print() { cout << "A" << "\t"; }
};

class B : public A {
public:
    void print() { cout << "B" << "\t"; }
};

class C : public A {
public:
    void print() { cout << "C" << "\n"; }
};

int main() {
    A a, *pa;
    B b; C c;
    a.print();
    b.print();
    c.print();
    pa = &a; pa->print();
    pa = &b; pa->print();
    pa = &c; pa->print();
}

hhhhh