0. 重构

重构是对程序内部的架构的调整。
重构强调的是在不改变"软件外部可观察的行为"前提下,对内部结构进行调整,使得从程序的外部功能上看,没有任何变化。
如下例子:
重构前代码如下:

#include <iostream>

class child
{
private:
public:
    child(){};
    void func(){
        std::cout << 123 << std::endl;
    }

};

int main(int argc, char const *argv[])
{
    child a;
    a.func();
    return 0;
}

程序运行后,输出123.
重构后的代码如下:

#include <iostream>

class child
{
private:
public:
    child(){};

    void f1(){std::cout << 1;}
    void f2(){std::cout << 2;}
    void f3(){std::cout << 3;}

    void func(){
        f1();
        f2();
        f3();
        std::cout << std::endl;
    }

};

int main(int argc, char const *argv[])
{
    child a;
    a.func();
    return 0;
}

main函数执行的时候,依然是调用a的func方法,程序的输出也是123,对于外部来说没有任何改变,但是func内部的实现方式已经改变。

1. 重写

重写(override)也叫覆盖。

明确一个概念:“函数签名”,函数签名不仅仅包括函数名,还包括函数的参数、参数的个数、参数的顺序、所在命名空间等信息。但是函数签名不包括函数的返回值类型,如果两个函数除了返回值类型不同以外,其他都一模一样,这在C++中是不被允许的。

重写是指不改变函数签名,改变的是一个函数内部。如下代码:

#include <iostream>

class parent
{
private:
public:
    parent(){};
    virtual void func(){
        std::cout << 123 << std::endl;
    }

};

class child : parent{
public:
    void func(){
        std::cout << 456 << std::endl;
    }

};

int main(int argc, char const *argv[])
{
    child a;
    a.func();
    return 0;
}

child继承parent类,重写了类内的func方法,没有改变函数签名,只改变函数内部代码。

2. 重载

重载是指不改变函数名,但改变函数的参数、参数个数、参数顺序。重载改变了函数的签名。

  • 两个同名函数要在同一个作用域下
  • 两个函数只有返回值不同,这是不允许的
  • 重载函数有默认参数的时候,语法上是可以通过的,但是调用函数可能会出现二义性,编译不允许。

代码如下:

#include <iostream>

class parent
{
private:
public:
    parent(){};
    virtual void func(){
        std::cout << 123 << std::endl;
    }

};

class child : parent{
public:
    void func(int a){
        std::cout << 456 << std::endl;
    }

};

int main(int argc, char const *argv[])
{
    child a;
    a.func(12);
    return 0;
}

child继承parent类,重载了类内的func方法,改变了函数签名(增加了一个参数),方法内部代码可以改变也可以不改变,但是不改变。