C/C++面试:成员函数的重载、继承、覆盖、隐藏

1、成员函数的重载

1.1、C++中的成员函数有4种,分别是普通成员函数,virtual虚函数,const成员函数。

  • void func(int a)
  • virtual void func(int a);
  • void func(int a) const;

如果在一个类中,声明这四种函数,哪是重复定义?哪些是重载?其中(1)(2)是重复定义,故编译不能通过,而(3)与(1)(2)是不同类型的函数,是重载。

因为类中的函数,都会自动添加一个自身类指针this,所以

  • void func(int a);          ------>  void func(Base *this, int a)
  • virtual void func(int a); ------>  virtual void func(Base *this, int a)
  • void func(int a) const;  ------>  void func(const Base *this, int a) const

所以(3)可以和(1)(2)重载,因为参数有一个const

1.2、类的成员函数重载是在同一个类中有多个同名的方法,这些方法的参数类型、参数个数或者方法属性(const)不同。

#define _CRT_SRCURE_NO_WARNINGS
#include <iostream>
#include <string>
using namespace std;

class MyClass
{
public:
	MyClass(int a = 0):c(a) {};
	void go(int a) { cout << "go "; };
	void go(char a){ cout << "char go "; };
	void print()const//函数体中不能修改数据成员对象,否则报错
	{
		cout << "const " << c << endl;
	}
	void print()//函数体中可修改成员对象
	{
		c = 23;
		cout << "non-const " << c << endl;
	}
private:
	int c;
};
void main()
{
	MyClass my;
	my.go(1);
	my.print();  //non-const  23
	
	const MyClass myC;
	myC.print();  //const 0
	system("pause");
}

成员函数重载特征:

  • 相同的范围
  • 函数名字相同
  • 参数类型,个数,顺序不同[包括const参数和非const参数]
  • virtual关键字可有可无

2、成员函数的继承  

#define _CRT_SRCURE_NO_WARNINGS
#include <iostream>
using namespace std;

class Base
{
public:
	void func(int a) { cout << "Base::f(int a)" << endl; };
	virtual void go(int a) { cout << "virtual Base: go(int a) " << endl; }; //virtual void func(Base *this, int a)
};

class Deviced :public Base
{
public:
	void h(int a) { cout << "Deviced::h(int a)" << endl; };
};
void main()
{
	Base b;
	b.func(3);
	b.go(4);
	Deviced d;
	d.func(32);
	d.go(4);
	d.h(32);
	system("pause");
}

子类deviced d种继承了父类种的virtual void g(int a), vpid f(int a);

3、成员函数的覆盖

覆盖是指派生类重新实现[或者改写]基类地成员函数,其特征是:

  • 不同的作用域
  • 函数名称相同
  • 参数列表相同
  • 基类函数必须是虚函数----->覆盖是针对基函数的

Deviced d种重新定义了基类的虚函数成员virtual void g(int a);

#define _CRT_SRCURE_NO_WARNINGS
#include <iostream>
using namespace std;

class Base
{
public:
	void func(int a) { cout << "Base::f(int a)" << endl; };
	virtual void go(int a) { cout << "virtual Base: go(int a) " << endl; }; //virtual void func(Base *this, int a)
};

class Deviced :public Base
{
public:
	void h(int a) { cout << "Deviced::h(int a)" << endl; };
	virtual void go(int a) { cout << "Deviced Base: go(int a) " << endl; };
};
void main()
{
	Base b;
	b.func(3);
	b.go(4);
	Deviced d;
	d.func(32);
	d.go(4);
	d.h(32);
	system("pause");
}

4、成员函数的隐藏

隐藏是指派生类的成员函数遮蔽了与其同名的基类成员函数:隐藏是在子类中看不到父类的函数

隐藏/重定义:指的是派生类的成员函数隐藏了基类函数的成员函数。

  • 在调用一个类的成员函数时候,编译器会沿着类的继承链逐步向上查找函数的定义,如果找到了就停止查找了。
  • 如果一个派生类和一个基类都有同一个同名函数,而编译器最后选择了派生类的函数,我们就说这个派生类的成员函数隐藏了基类的成员函数,也就是阻止了编译器继续向上查找函数的定义。
#define _CRT_SRCURE_NO_WARNINGS
#include <iostream>
using namespace std;

class Base {
public:
	virtual void f(float x) { cout << "virtual Base::f(float)" << x << endl; }
	void g(float x) { cout << "Base::g(float)" << x << endl; }
    void h(float x) { cout << "Base::h(float)" << x << endl; }
};

class Deviced :public Base
{
public:
	virtual void f(float x) { cout << "virtual Deviced::f(float)" << x << endl; }
	void g(int x) { cout << "Deviced::g(int)" << x << endl; }
	/*派生类的函数与基类的函数同名不同参,此时,无论有无vritual,*/
	void h(float x) { cout << "Deviced::h(float)" << x << endl; }
};
void main()
{
	Deviced d;
	Base *pb = &d;   //基类指针指向派生类
	pb->f(3.14f);    //覆盖 
	/*virtual Deviced::f(float):f是一个虚函数,派生类重写了这个虚函数
	不同的范围,函数名字相同,参数相同,是基函数
	派生类对象/指向派生类的指针:调用了子类的同名函数
	基类对象:调用基类中的函数
	*/
	pb->g(3.14f);     //Base::g(float)
	/*不同类中,不是重载;不是virtual不是覆盖,没关系
	基类指针只能访问基类g
	*/
	pb->h(3.14f);  //Base::h(float)
	Deviced *pd = &d;     //派生类指针调用派生对象 
	pd->f(3.14f);     //  virtual Deviced::f(float)
	pd->g(3.14f);     //Deviced::g(int)
	pd->h(3.14f);     //Deviced::h(float),隐藏是在子类中看不到父类的函数
	system("pause");
}

C++ 中重载和重写,重定义的区别

 

(1)重载:指的是同一可访问区内被声明的几个具有不同参数列表的同名函数,依赖于 C++函数名字的修饰 会将参数加在后⾯,可以是参数类型,个数,顺序的不同。根据参数列表决定调⽤哪个函数,重载不关⼼函数的返 回类型。

(2)重写:派生类中重新定义父类中除了函数体外完全相同的虚函数。

  • 被重写的函数不能是static的,一定要是虚函数,而且其他一定要完全相同。
  • 重写和被重写的函数是在不同的类当中的,重写函数的访问修饰符是可以不同的,比如virtual 中是 private 的,派⽣类中重写可以改为 public。

(3)重定义(隐藏):指的是派生类的成员函数隐藏了基类函数的非virtual成员函数。

  • 在调用一个类的成员函数时候,编译器会沿着类的继承链逐步向上查找函数的定义,如果找到了就停止查找了。
  •  如果一个派生类和一个基类都有同一个同名函数,而编译器最后选择了派生类的函数,我们就说这个派生类的成员函数隐藏了基类的成员函数,也就是阻止了编译器继续向上查找函数的定义。

               

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值