天天看点

C++ virtual关键字

文章目录

    • 1. virtual简单多态性
    • 2.virtual纯虚函数
    • 3. vitual关键字的其他用法
      • 虚继承

我们知道C++是一种面向对象的编程语言,其中很重要的语法特性就是多态。具体来说,有1、同名函数重载;

2、子类重载父类的虚方法等等。

这里主要重点了解第二种,C++有关键字virtual进行虚方法的声明。这样的好处就是,子类在实现自己的方法时,可以复用父类的这个函数名称,以达到简洁明了作用。

举个栗子:

1. virtual简单多态性

class base
{
public:
	base() {}
	~base() {}

	void say() 
		{
			sayHello();
		}
	virtual void sayHello()
		{
			std::cout << "hi , i'm base" << std::endl;
		}
};

           

以上,我们定义了一个基类base,通过关键字定义虚函数sayHello,进一步,我们定义子类child派生于base

class child : public base
{
public:
	child(){}
	~child(){}
	
	void sayHello() override
		{
			std::cout << "hi , i'm child" << std::endl;
		}
};

           

这里我们用override关键字显示声明我们重载了sayHello,,我们在main中使用child的say方法时:

int main()
{
	child c;
	c.say();
	return (0);
}
           

将输出

hi , i’m child

2.virtual纯虚函数

当然这里,我们预期基类base是可以被实例化的。但是大多数应用中,我们往往希望有一个一般的类能够被其他类继承且不能被实例化,这个类实现一些公有的特性,这时候就需要用到纯虚函数的概念。

举个栗子

class base
{
public:
	base() {}
	~base() {}
	
	// 声明为纯虚函数
	virtual void sayHello() = 0;
};

           

这样一来,编译时都会报错:

C++ virtual关键字
图1 报错信息
  • 说明,此时base已经为一个抽象类不能被实例化。而且,达到了我们要求所有派生于此基类的派生类都实现这一公有的属性的要求。
class child : public base
{
public:
	child2(){}
	~child2(){}

	void show() override
	{
		std::cout << "i'm child" << std::endl;
	}

};
           

在main函数中实例化child,并调用show函数

int main()
{
	child c;
	c.show();
	return(0)
}
           

将输出

i’m child

3. vitual关键字的其他用法

虚继承

  • virual关键字还能够进行虚继承,从而避免多个继承于父类的子类拷贝的问题。
  • 具体而言,在一个派生类中保留间接基类的多份同名成员,虽然可以在不同的成员变量中分别存放不同的数据,但大多数情况下这是多余的:因为保留多份成员变量不仅占用较多的存储空间,还容易产生命名冲突。
  • 假如类 A 有一个成员变量 a,那么在类 D 中直接访问 a 就会产生歧义,编译器不知道它究竟来自 A -->B–>D这条路径,还是来自 A–>C–>D 这条路径。

    而虚基类可以很好解决这个问题,保留上述中类A的唯一一份拷贝。本质就是消除歧义,共享变量的一种方式。类似于静态变量共享的功能。

    语法形式如下:

class C: virtual public A

继续阅读