最近公司招人,发现好多C++面试者基础概念理不清楚。今天恰好有点时间,把这些梳理下。有人读到的话也算为大家做点贡献,哈哈。
1, 函数重载(overload)
如果同一作用域内的几个函数名字相同但形参列表不同,我们称之为重载(overloaded)函数。
void print(const char *p); void print(const int *beg, const int *end); void print(const int ia[], size_t size);
这些函数接受的形参类型或个数不一样,但是执行的操作非常类似。当调用这些函数时,编译器会根据传递的实参类型推断想要的是哪个函数。函数的名字仅仅是让编译器知道它调用的是哪个函数,而函数重载可以在一定程度上减轻程序员起名字、记名字的负担。
关键提取:同一作用域、函数名相同形参列表不同(类型或者个数)
//重载和const形参 //顶层的const不影响传入函数的对象 Record lookup(Phone); Record lookup(const Phone); //重复声明了Record lookup(Phone) Record lookup(Phone*); Record lookup(const Phone*); //重复声明了Record lookup(Phone*) //如果形参是某种类型的指针或者引用,则通过区分其指向的是常量对象还是非常量对象可以实现函数重载,此时的const是底层的 Record lookup(Account&); Record lookup(const Account&); //新函数,作用于常量引用 Record lookup(Account*); Record lookup(const Account*); //新函数,作用于指向常量的指针 //当我们传递一个非常量对象或者指向非常量对象的指针时,编译器会优先选用非常量版本的函数
2,覆盖(override)
在基类(base class)和派生类(derived class)之间,基类有虚函数 virtual void fun(),派生类重新编写改函数 void fun() override,则为派生类覆盖从基类继承而来的定义。这个跟多态相关,详见https://www.cnblogs.com/baichenshan/p/8901819.html。
class CBase { public: virtual void fun(); } class CDerived : public CBase { public: void fun() override; //覆盖基类的fun函数 }
关键提取:关系是多个类之间,基类改函数必须是虚函数(virtual)
3,函数隐藏
派生类能重用定义在基类中的名字,此时定义在内层作用域(即派生类)的名字将隐藏定义在外层作用域(即基类)的名字。
如果派生类的成员与基类的某个成员同名,则派生类将在其作用域内隐藏该基类成员。即使派生类成员和基类成员的形参不一致,基类成员也仍然会被隐藏。
class CBase { public: void fun(); } class CDerived : public CBase { public: void fun() ; //派生类作用域内隐藏基类的fun函数 }
关键提取:关系是多个类之间,派生类和基类函数名相同,函数无virtual修饰,形参可不相同
综合思考
class Base { public: virtual int fcn(); }; class D1 : public Base { public: // 隐藏基类的 fcn, 这个 fcn 不是虚函数。 D1 继承了 Base::fcn() 的定义 int fcn(int); // 形参列表与Base中的fcn不一致 virtual void f2(); // 是一个新的虚函数,在 Base 中不存在 }; class D2 : public D1 { public: int fcn(int); // 是一个非虚函数,隐藏了 D1::fcn(int) int fcn(); // 覆盖了 Base 的虚函数 fcn void f2(); // 覆盖了 D1 的虚函数 f2 } /////////////////////////////////////////////////////////////////////////// Base bobj; D1 d1obj; D2 d2obj; Base *bp1 = &bobj, *bp2 = &d1obj, *bp3 = &d2obj; bp1->fcn(); // 虚调用,将在运行时调用 Base::fcn bp2->fcn(); // 虚调用,将在运行时调用 Base::fcn bp3->fcn(); // 虚调用,将在运行时调用 D2::fcn bp2->f2(); // 错误:Base没有名为f2的成员 D1 *d1p = &d1obj; D2 *d2p = &d2obj; d1p->f2(); // 虚调用,将在运行时调用 D1::f2 d2p->f2(); // 虚调用,将在运行时调用 D2::f2 Base *p1 = &d2obj; D1 *p2 = &d2obj; D2 *p3 = &d2obj; p1->fcn(42); // 错误:Base中没有接受一个int的fcn p2->fcn(42); // 静态绑定,调用 D1::fcn(int) p3->fnc(42); // 静态绑定,调用 D2::fcn(int)
以上内容皆来自 C++ Primer , 多看书,多思考,多练习,基础自然扎实。