欢迎您访问程序员文章站本站旨在为大家提供分享程序员计算机编程知识!
您现在的位置是: 首页

C++虚函数

程序员文章站 2024-03-21 12:05:22
...

虚函数

在C++中基类必须将它的两种成员函数区分开来:一种是基类希望其派生类进行覆盖的函数;另一种是基类希望派生类直接继承而不要改变的函数,对于前者通常定义为虚函数,当我们使用指针引用对虚函数的调用将被动态绑定,即根据所绑定的对象不同,所执行的函数不同,有可能是基类的,也有可能是派生类的。C++中多态就是通过虚函数来实现的。

基类通过在其成员函数的声明语句前加上关键字virtual使得该函数执行动态绑定,关键字virtual只能出现在类内部的声明语句之前而不能用于类外部的函数定义。

如果基类把一个函数声明成虚函数,则该函数在派生类中隐式地也是虚函数;如果派生类没有覆盖基类中的某个成员函数,则该虚函数的行为类似于其他的普通成员,派生类会直接继承其在基类中的版本。

派生类可以在它覆盖的函数前使用virtual关键字,但不是非得这么做,C++11新标准允许派生类显式注明它使用某个成员函数覆盖了它继承的虚函数,具体做法是在形参列表或const限定符或引用限定符后面添加一个关键字override。

override的好处是如果我们使用了override标记了某个函数,但该函数并没有覆盖已存在的虚函数,此时编译器将会报错。

我们还能把某个函数指定为final,使之后任何尝试覆盖该函数的操作都引发错误。

class Person
{
public:
	virtual void jump() final
	{
		std::cout << "person jump..." << std::endl;
	};

	virtual void run()
	{
		std::cout << "person run..." << std::endl;
	};
};

class Worker :public Person
{
public:
	virtual void jump() override //错误,不能覆盖标记为final的虚函数
	{
		std::cout << "worker jump..." << std::endl;
	};
	virtual void run() override
	{
		std::cout << "worker run..." << std::endl;
	};
};

int main(void)
{
	Person* person = new Worker();
	person->run();//worker run...

	Person&& person2 = Worker();
	person2.run();//worker run...

	Person person3 = Worker();
	person3.run();//person run...
	system("pause");
	return 0;
}

虚函数与默认实参

虚函数也可以拥有默认实参,调用虚函数使用默认实参时,该实参值由本次调用的静态类型决定,如果我们通过基类的引用或指针调用函数,则使用基类中定义的默认实参,即使实际运行的是派生类中的函数版本也是如此。所以如果虚函数使用默认实参,则基类和派生类中定义的默认实参最好一致。

强制执行某个虚函数版本

某些情况下需要调用特定的虚函数版本,例如派生类调用基类的虚函数版本,使用作用域运算符可以实现这一目的。

class Person
{
public:
	virtual void run()
	{
		std::cout << "person run..." << std::endl;
	};
};

class Worker :public Person
{
public:
	virtual void run() override
	{
		std::cout << "worker run..." << std::endl;
	};
};

int main(void)
{
	Person* person = new Worker();
	person->Person::run();//person run...
	system("pause");
	return 0;
}
相关标签: 虚函数