天天看点

C++小细节19:Override,Overload,Overwrite区别重载(Overload)覆盖(Overwrite)重写(Override)知识拓展参考

11/15/2020

文章目录

  • 重载(Overload)
  • 覆盖(Overwrite)
  • 重写(Override)
    • 虚函数默认实参问题
  • 知识拓展
    • 静态与动态类型
  • 参考

重载(Overload)

函数重载,必须在同一个作用域之中,几个函数名字相同但形参列表不同

namespace FunctionOverload{
	void foo();
	void foo(int a);
	void foo(float a);
	void foo(int a, float b);
};

class FunctionOverload
{
public:
	void foo();
	void foo(int a);
	void foo(float a);
	void foo(int a, float b);
};

void main()
{
	FunctionOverload::foo(2.4);
	FunctionOverload::foo(2);

	FunctionOverload bar;
	bar.foo();
	bar.foo(1,3.3);
}
           
  • 形参数量和形参列表不同
  • 返回值不同是错误的
  • 顶层的const是无法区分重载的,但是底层的const可以
Record lookup(Phone);
Record lookup(const Phone); //错误的,重复声明

Record lookup(Phone*);
Record lookup(Phone *const); //错误的,重复声明

//====================================
Record lookup(Phone);
Record lookup(const &Phone); //可以,常量引用

Record lookup(Phone*);
Record lookup(const Phone *); //可以,指向常量的指针
           

覆盖(Overwrite)

不同作用域之间发生的覆盖,即隐藏外部相同的名字

class Base
{
public:
	void foo(float a);
	void foo(int b); //overload
};

class Derived:public
{
public:
	void foo(double c);	//覆盖了Base的foo

	void bar()
	{
		foo(2.3);
		Base::foo(3);
	}
};
           

重写(Override)

使用virtual 关键字的虚函数为重写,主要体现在继承关系并且存在动态类型

class Base
{
public:
 virtual void foo(int a,int c);	//虚函数
 void foo(int d);	//Overload
 
};

class Derived:public Base
{
public:
 virtual void foo(int a,int c) override;	//虚函数
 void foo(int d);	//Overwrite + Overload
};
           

虚函数默认实参问题

class Base
{
public:
 virtual void foo(int a = 0);	//虚函数
 
};

class Derived:public Base
{
public:
 virtual void foo(int a = 2) override;	//虚函数
};

void main()
{
	Base* b = new Derived;
	b->foo(); 	//a=?

	b->Base::foo(); //强制调用Base中的foo函数,即回避虚函数机制
}
           
答案a等于0,由静态类型决定的

知识拓展

静态与动态类型

//静态
Base abase
Derived b;

//动态类型
Base *c = new Derived;
Base* d = &b;

//错误的  base ---> derived
Derived* e = &base;
Derived& g = base;

           
  • 基类不能转换为派生类,但是派生类可以向基类转换
  • 派生类向基类转换只针对指针和引用类型
class Base
{
public:
 int a;
 int d;
};

class Derived:public Base
{
public:
	int e;
	int f;
};

Derived d;
d.a = 3;
d.d = 4;
d.e = 5;
d.f = 6;
Base base(d);  //拷贝构造函数,最多初始化a,d,但是不能初始化e,f,因为调用Base::Base(const Base&) 函数
           
当我们用一个派生类对象为一个基类对象初始化或赋值时,只有该派生类对象中的基类部分会被拷贝,移动或赋值,它的派生类会被忽略掉

参考

  • C Primer 第五版 6.4,15.3

继续阅读