• 重载: 在同一作用域中,两个函数名相同,但是参数列表不同(个数、类型、顺序),返回值类型没有要求
  • 重写(覆盖): 子类继承了父类,父类中的函数是虚函数,在子类中重新定义了这个虚函数,这种情况是重写或覆盖;
  • 重定义: 派生类中函数与基类中的函数同名(形参没有要求),但是这个函数在基类中并没有被定义为虚函数
  • 隐藏: 派生类中重定义了父类的函数,此时基类的函数会被隐藏;
  • 模板: 函数模板是一个通用函数,函数的类型和形参不直接指定而用虚拟类型来代表,只适用于 参数个数相同而类型不同 的函数。
  • 构造函数可以被重载,析构函数不可以被重载。因为构造函数可以有多个且可以带参数, 而析构函数只能有一个,且不能带参数

1、重载

  1. 类的静态函数也可以重载;
  2. 形参中一级指针和二级指针被认为是不同类型的参数;
class A{
public:
    A(int a){
        m_a = a;
    }
    void print(){
        cout << "print()" << "m_a = " << m_a << endl;
    }
    void freeP(A ** p){
        if(p == NULL){
            return;
        }
        if(*p != NULL){
            free(*p);
            *p = NULL;
        }
    }
    void freeP(A * p){
        if(p != NULL){
            free(p);
            p = NULL;
        }
    }
    static void printS(){
        cout << "printS() s_a = " << s_a << endl;
    }
    static void printS(int s){
        cout << "printS(int s) " << s_a * s << endl;
    }
    static void printS(void *p, int s){    
        cout << "printS(void *p, int s) " << ((A*)p)->m_a * s << endl;
    }
    
    static int s_a;
private:
    int m_a;
};
int A::s_a = 0;
int main( )
{  
    A *a = new A(1);
    a->printS(a, 20);
    a->print();
    A::s_a = 10;
    a->printS();
    a->printS(10);
    a->freeP(a);
    if(a == NULL){
        cout << "*a is not valid" << endl;
        return 0;
    }
    cout << "*a is valid" << endl;
    a->print();
    return 0;
}

输出:

Start
printS(void *p, int s) 20
print()m_a = 1
printS() s_a = 10
printS(int s) 100
*a is valid
print()m_a = 0
0
Finish
  1. 重写(覆盖)与重定义(隐藏)
struct B{
    virtual void print(){
        cout << "B::print" << endl;
    }
    void printT(){
        cout << "B::printT" << endl;
    }
};
struct D:B{
    void print() override{
        cout << "D::print" << endl;
    }
    void printT(int a){
        cout << "D::printT" << endl;
    }
};
int main()
{
    D* d = new D;
    d->print();
    d->printT(0);
    B* b = static_cast<B*>(d);
    b->print();
    b->printT();
    
    return 0;
}

输出:

D::print
D::printT
D::print
B::printT
#include <iostream>
using namespace std;
class A{
public:
    virtual void f(){
        cout << "A::f\n";
    }
    void g(){
        cout << "A::g\n";
    }
};
// 隐藏和覆盖
class B: protected A{ // 通过非 public 继承,隐藏父类函数
public:
    // using A::g;      
    void g(){           // 覆盖父类的 g(), 但并未隐藏
        cout << "B::g\n";
    }
    void f()override{   // 通过虚函数覆盖父类函数
        cout << "B::f\n";
    }
    A getA(){
        return *this;
    }
};
int main()
{
    B b;
    A* p = (A*)&b;   
    // b.A::f();    // error: ‘class A A::A’ is inaccessible within this context
                    // 父类 g() 被隐藏
    p->A::f();      // A::f
    p->f();         // B::f
    b.f();          // B::f
    b.g();          // B::g 
    p->g();         // A::g
    A aa = b.getA();
    aa.g();         // A::g
    aa.f();         // A::f

    return 0;
}