参考文章:c++三大概念要分清–重载,隐藏(重定义),覆盖(重写)
重载
在同一个作用域内
1. 函数名相同
2. 参数列表不同(参数个数不同,或者参数类型不同,或者参数个数和参数类型都不同)
3. 返回值类型可相同也可不同
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44
| test_ooh.cpp
namespace {
int Add(int a, int b) { PRINT_INFO("int " << __func__ << "(int, int)"); return a + b; }
double Add(double a, double b) { PRINT_INFO("double " << __func__ << "(double, double)"); return a + b; }
}
class test_ooh { public: test_ooh(){} ~test_ooh(){} int Add(int a, int b) { PRINT_INFO("int " << "test_ooh::" << __func__ << "(int, int)"); return a + b; }
double Add(double a, double b) { PRINT_INFO("double " << "test_ooh::" << __func__ << "(double, double)"); return a + b; } };
Add(1, 2); Add(1.2, 3.2);
test_ooh to; to.Add(1, 2); to.Add(1.3, 2.2);
|
输出结果:
[INFO]: int Add(int, int)
[INFO]: double Add(double, double)
[INFO]: int test_ooh::Add(int, int)
[INFO]: double test_ooh::Add(double, double)
- 匿名 namespace 下的两个函数 Add() ,在同一作用域,函数名相同,参数类型不同,就构成了 C++ 中的函数重载;
- 调用函数名相同的函数,会根据 实参的类型和实参顺序以及实参个数选择相应的函数;
- C++ 函数重载是一种 静态多态(又叫做静态联编,静态绑定,静态决议)
重写(覆盖)
不在同一个作用域内(分别在父类和子类):
1. 函数名相同
2. 参数列表相同
3. 返回值类型相同(协变除外)
4. 基类函数必须有 virtual 修饰(即虚函数)
5. 父子类中的函数的访问修饰符可以不同
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67
| test_ooh.cpp
class Base { public: Base(){} ~Base(){}
virtual void show() { PRINT_INFO("Base::show()"); }
virtual Base& getThis() { PRINT_INFO("Base::getThis()"); return *this; } };
class Derived : public Base { public: Derived(){} ~Derived(){}
virtual void show() { PRINT_INFO("Derived::show()"); }
Derived& getThis() { PRINT_INFO("Derived::getThis()"); return *this; } };
namespace { void callFunc(Base& b) { b.show(); b.getThis(); }
void callFunc(Base* b) { b->show(); b->getThis(); } }
Base b; Derived d;
callFunc(b); callFunc(d); callFunc(&b); callFunc(&d);
|
输出结果:
[INFO]: Base::show()
[INFO]: Base::getThis()
[INFO]: Derived::show()
[INFO]: Derived::getThis()
[INFO]: Base::show()
[INFO]: Base::getThis()
[INFO]: Derived::show()
[INFO]: Derived::getThis()
- 父类函数为虚函数;
- 当在子类中定义了一个与父类完全相同的虚函数时,则称子类的这个函数重写(也称覆盖)了父类的这个虚函数;(子类中的虚函数和父类中的虚函数,函数名,参数个数,参数类型,返回值类型都相同;这种情况下子类的这个虚函数重写的父类中的虚函数,构成了重写)
- 协变 ——— 是说子类中的虚函数和父类中的虚函数,函数名,参数个数,参数类型都相同,只是返回值类型不同;父类的虚函数返回父类的指针或者引用,子类虚函数返回子类的指针或者引用;这种情况下子类的这个虚函数也重写了父类中的虚函数,也构成了重写;———— 我们把这种特殊的情况叫做协变
重定义(隐藏)
不在同一个作用域内(分别在父类和子类):
1. 函数名相同
2. 在父类和子类中只要不构成重写的都是重定义
3. 重定义的不光是类的成员函数,还可以是类的成员变量
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107
| test_ooh.cpp
class Base { public: Base():i_(0){} Base(int i):i_(i){} ~Base(){}
virtual void show() { PRINT_INFO("Base::show()"); }
virtual Base& getThis() { PRINT_INFO("Base::getThis()"); return *this; }
virtual void test_hiding() { PRINT_INFO("Base::test_hiding()"); }
void test_show(int a) { PRINT_INFO("Base::test_show(int) , a = " << a); }
int test_hiding2() { PRINT_INFO("Base::test_hiding2()");
return 0; }
public: int i_; };
class Derived : public Base { public: Derived(){} Derived(int i):Base(i),i_(0){} ~Derived(){}
virtual void show() { PRINT_INFO("Derived::show()"); }
Derived& getThis() { PRINT_INFO("Derived::getThis()"); return *this; }
void test_hiding(int a) { PRINT_INFO("Derived::test_hiding(int) , a = " << a); }
void test_show(int a, int b) { PRINT_INFO("Derived::test_show(int) , a = " << a << ",b = " << b); }
void test_hiding2() { PRINT_INFO("Derived::test_hiding2()"); }
public: int i_; };
Base b1; Derived d1(1); b1.test_hiding(); d1.Base::test_hiding(); d1.test_hiding(1);
PRINT_INFO("Derived::i_ = " << d1.i_); PRINT_INFO("Base::i_ = " << d1.Base::i_);
b1.test_show(1); d1.Base::test_show(1); d1.test_show(1, 2);
b1.test_hiding2(); d1.Base::test_hiding2(); d1.test_hiding2();
|
输出结果:
[INFO]: Base::test_hiding()
[INFO]: Base::test_hiding()
[INFO]: Derived::test_hiding(int) , a = 1
[INFO]: Derived::i_ = 0
[INFO]: Base::i_ = 1
[INFO]: Base::test_show(int) , a = 1
[INFO]: Base::test_show(int) , a = 1
[INFO]: Derived::test_show(int) , a = 1,b = 2
[INFO]: Base::test_hiding2()
[INFO]: Base::test_hiding2()
[INFO]: Derived::test_hiding2()