C++-Record40—重写、重载、重定义三个概念的辨析

拥有回忆 提交于 2020-01-30 06:57:41

目录

概念定义

案例分析

总体代码


概念定义

函数重载:必须在同一类中进行,且子类无法重载父类的函数,父类同名函数将被名称覆盖不会发生重载,重载是在编译期间根据参数类型和个数决定函数调用的。

函数重写:必须发生于父类与子类之间,并且,父类与子类中的函数必须有完全相同的原型,使用virtual声明之后能够产生多态(如果不使用virtual,那叫重定义),多态是在运行期间根据具体对象的类型决定函数调用的。 

案例分析

本篇对重写、重载、重定义三个概念进行举例和辨析,先上案例,定义一个父类:

class Parent
{
	//这个三个函数都是重载关系
public: 
	void abc()
	{
		printf("abc");
	}

	virtual void func() 
	{
		cout<<"func() do..."<<endl;
	}
	virtual void func(int i)
	{
		cout<<"func() do..."<<i<<endl;
	}
	virtual void func(int i, int j)
	{
		cout<<"func() do..."<<i<< " "<<j<<endl;
	}

	virtual void func(int i, int j, int m , int n)
	{
		cout<<"func() do..."<<i<< " "<<j<<endl;
	}
protected:
private:
};

在这个类中,同名的func函数出现了四次,每次func函数所对应的输入参数都不一样,均在一个类中,这就是函数重载。 那么接着再定义一个子类:

class Child : public Parent
{
	
public: 
	void abc()
	{
		printf("child abc");
	}
	/*
	void abc(int a)
	{
		printf("child abc");
	}
	*/
	virtual void func(int i, int j)
	{
		cout<<"func(int i, int j) do..."<<i<< " "<<j<<endl;
	}
	virtual void func(int i, int j, int k)
	{
		cout<<"func(int i, int j) do.."<< endl; 
	}
protected:
private:
};

同理,在这个子类里面,又有两个func函数,那定义在子类中的两个函数func,是函数重载的关系。

那么现在的func函数就拢共有5个了,它们之间各自是什么关系呢?先画一个示意图:

 那么,可以看成,父类中的"virtual void func(int i, int j)"和子类中的"virtual void func(int i, int j)",这两个函数不是在同一个类里面,而且函数原型完全一样,而且,它们加了"virtua"关键字,那么这俩函数的关系就是重写。如果还是以上条件,只是没有加"virtual"关键字,那么它俩的关系就是重定义了!

务必强调,必须是函数原型完全一样才行,就是说不仅函数名称要一样,而且函数的输入参数的变量名和数量也必须完全一致才可以

再往下看,在主调函数中定义一个由子类创建的对象c1:

//重载重写和重定义
void main()
{
	//: error C2661: “Child::func”: 没有重载函数接受 0 个参数
	Child c1;

	//c1.func();
	//子类无法重载父类的函数,父类同名函数将被名称覆盖
	c1.Parent::func();

	//1 C++编译器 看到func名字 ,因子类中func名字已经存在了(名称覆盖).所以c++编译器不会去找父类的4个参数的func函数
	//2 c++编译器只会在子类中,查找func函数,找到了两个func,一个是2个参数的,一个是3个参数的.
	//3 C++编译器开始报错.....  error C2661: “Child::func”: 没有重载函数接受 4 个参数
	//4 若想调用父类的func,只能加上父类的域名..这样去调用..
	c1.func(1, 3, 4, 5);

	//c1.func();
	//func函数的名字,在子类中发生了名称覆盖;子类的函数的名字,占用了父类的函数的名字的位置
	//因为子类中已经有了func名字的重载形式。。。。
	//编译器开始在子类中找func函数。。。。但是没有0个参数的func函数 


	cout<<"hello..."<<endl;
	system("pause");
	return ;
}

如果想通过像在父类中那样重载的方式,来在子类中重载父类的函数,是不可能的,因为这样做,只会将父类的函数给之间覆盖掉(通过子类去调用父类函数,调用不起来,这是在编译器在运行时候,如果发现所碰到的函数在子类中有,就只会在子类中找对应的函数名称的函数,不会再去父类中去找了,那怕发现子类中的这个函数名称一致,但参数不一致,也只会报错,说没找到,而不会再去父类中去找了),如果非想达到重载的功能,就在子类中添加完父类的重载函数后,想去调用父类的函数时,加上父类的作用域符号,显式的写出来,这样才能调用在父类中定义的同名函数,如上段代码那样:

	c1.Parent::func();

总体代码

dm16_重载重写重定义.cpp


#include <iostream>
using namespace std;

//重写 重载 重定义
//重写发生在2个类之间
//重载必须在一个类之间

//重写分为2类
//1 虚函数重写  将发生多态
//2 非虚函数重写 (重定义)

class Parent
{
	//这个三个函数都是重载关系
public: 
	void abc()
	{
		printf("abc");
	}

	virtual void func() 
	{
		cout<<"func() do..."<<endl;
	}
	virtual void func(int i)
	{
		cout<<"func() do..."<<i<<endl;
	}
	virtual void func(int i, int j)
	{
		cout<<"func() do..."<<i<< " "<<j<<endl;
	}

	virtual void func(int i, int j, int m , int n)
	{
		cout<<"func() do..."<<i<< " "<<j<<endl;
	}
protected:
private:
};


class Child : public Parent
{
	
public: 
	void abc()
	{
		printf("child abc");
	}
	/*
	void abc(int a)
	{
		printf("child abc");
	}
	*/
	virtual void func(int i, int j)
	{
		cout<<"func(int i, int j) do..."<<i<< " "<<j<<endl;
	}
	virtual void func(int i, int j, int k)
	{
		cout<<"func(int i, int j) do.."<< endl; 
	}
protected:
private:
};


//重载重写和重定义
void main()
{
	//: error C2661: “Child::func”: 没有重载函数接受 0 个参数
	Child c1;

	//c1.func();
	//子类无法重载父类的函数,父类同名函数将被名称覆盖
	c1.Parent::func();

	//1 C++编译器 看到func名字 ,因子类中func名字已经存在了(名称覆盖).所以c++编译器不会去找父类的4个参数的func函数
	//2 c++编译器只会在子类中,查找func函数,找到了两个func,一个是2个参数的,一个是3个参数的.
	//3 C++编译器开始报错.....  error C2661: “Child::func”: 没有重载函数接受 4 个参数
	//4 若想调用父类的func,只能加上父类的域名..这样去调用..
	c1.func(1, 3, 4, 5);

	//c1.func();
	//func函数的名字,在子类中发生了名称覆盖;子类的函数的名字,占用了父类的函数的名字的位置
	//因为子类中已经有了func名字的重载形式。。。。
	//编译器开始在子类中找func函数。。。。但是没有0个参数的func函数 


	cout<<"hello..."<<endl;
	system("pause");
	return ;
}

 

标签
易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!