一步一步学习C++(类)之虚函数和纯虚数

1、该函数必须与基类的虚函数有相同的名称
2、该函数必须与基类的虚函数有相同的参数个数和相对应的参数类型
3、该函数必须与基类的虚函数有相同的返回值,或满足类型兼容规则的指针,引用型返回值。

4、如果派生类的函数满足以上三个条件系统就会自动把其定为虚函数。这时派生类的虚函数便覆盖了基类的虚函数,不仅如此派生类中的虚函数还会隐藏基类中同名函数的所有其他重载形式。

5、只有虚函数是动态绑定的,如果派生类需要修改基类的行为,即重写与基类的函数同名的函数,就应该在基类中将相应的函数声明为虚函数。而基类中声明的非虚函数,通常代表不希望被派生类改变的功能,也不能实现多态。因此一般不要重写继承而来的非虚函数。

6、在重新继承来的虚函数时,如果有默认形参值,千万不要定义不同的值。原因是谁然虚函数是动态绑定的,但是默认形参值是静态绑定的,也就是说,通过一个指向派生类对象的基类指针,可以访问到派生类的虚函数,但默认形参值却只能来自基类的定义;

// VirtualAndDT.cpp : 定义控制台应用程序的入口点。
//

#include "stdafx.h"
#include<iostream>
using namespace std;

//虚函数经典列子
class B0
{
public:
	virtual void display()//如果没有虚函数 下面的main函数内容将输出都是基类的函数
	{
		cout <<"我是显示页面B0" << endl;
	}

};
class B1:public B0
{
public:
	void display()
	{
		cout << "我是显示页面B1" << endl;
	}
};

void fun(B0 *p)
{
	p->display();
}

void main()
{
	B0 *p;//基类指针
	B0 b0;
	B1 b1;
	p = &b0;
	fun(p);
	p = &b1;
	fun(p);
	system("pause");
}

     虚函数是动态绑定的,但是默认形参值是静态绑定的,也就是说,通过一个指向派生类对象的基类指针,可以访问到派生类的虚函数,但默认形参值却只能来自基类的定义

// VirtualAndDT.cpp : 定义控制台应用程序的入口点。
//

#include "stdafx.h"
#include<iostream>
using namespace std;

//虚函数
class B0
{
public:
	virtual void display(int a=5)
	{
		cout <<  "我是显示页面B0"  << a << endl;
	}
};
class B1:public B0
{
public:
	void display(int a=6)
	{
		cout <<  "我是显示页面B1" << a << endl; // 注意输出是 5
	}
};
class B2:public B1
{
public:
	void display(int a = 7) //  注意输出是5
	{
		cout <<  "我是显示页面B2" << a<< endl;
	}
};
void fun(B0 *p)
{
	p->display();
}
void main()
{
	B0 *p;
	B0 b0;
	B1 b1;
	B2 b2;
	p = &b0;
	fun(p);
	p = &b1;
	fun(p);
	p=&b2;
	fun(p);
	system("pause");
}


// VirtualAndDT.cpp : 定义控制台应用程序的入口点。
//

#include "stdafx.h"
#include<iostream>
using namespace std;

class B0
{
public:
	virtual void display()  //显示定义虚函数
	{
		cout <<  "我是显示页面B0" << endl;
	}
};
class B1:public B0
{
public:
	void display()    //默认虚函数
	{
		cout <<  "我是显示页面B1" << endl;
	}
};
class B2:public B1
{
public:
	void display()
	{
		cout <<  "我是显示页面B2" << endl;
	}
};
void fun(B0 *p)
{
	p->display();
}
void main()
{
	B0 *p;
	B0 b0;
	B1 b1;
	B2 b2;
	p = &b0;
	fun(p);
	p = &b1;
	fun(p);
	p=&b2;
	fun(p);
	system("pause");
}


二、纯虚函数

纯虚函数是在基类中只声明虚函数而不给出具体的函数定义体,将它的具体定义放在各派生类中,称此虚函数为纯虚函数.通过该基类的指针或引用就可以调用所有派生类的虚函数,基类只是用于继承,仅作为一个接口,具体功能在派生类中实现.

纯虚函数的声明如下:(注:要放在基类的定义体中)

   virtual 函数原型=0;

声明了纯虚函数的类,称为抽象类。

  • 抽象类中可以有多个纯虚函数

  • 不能声明抽象类的对象,但可以声明指向抽象类的指针变量和引用变量

  • 抽象类也可以定义其他非纯虚函数

  • 如果派生类中没有重新定义基类中的纯虚函数,则在派生类中必须再将该虚函数声明为纯虚函数

  • 从抽象类可以派生出具体或抽象类,但不能从具体类派生出抽象类

  • 在一个复杂的类继承结构中,越上层的类抽象程度越高,有时甚至无法给出某些成员函数的实现,显然,抽象类是一种特殊的类,它一般处于类继承结构的较外层

  • 引入抽象类的目的,主要是为了能将相关类组织在一个类继承结构中,并通过抽象类来为这些相关类提供统一的操作接口

class B0
{
public:
	virtual void display() const =0;//如果没有纯虚函数 下面的main函数内容将输出都是基类的函数
	
};
class B1:public B0
{
public:
	void display() const
	{
		cout <<  "我是显示页面B1" << endl;
	}
};

void fun(B0 *p)
{
	p->display();
}
void main()
{
	B0 *p;
	//B0 b0;
	//error C2259: “B0”: 不能实例化抽象类
	 B1 b1;
	//p = &b0;
	//fun(p);
	p = &b1;
	fun(p);
	system("pause");
}

/*
virtual void display() const =0;//纯虚函数
(1)=0说明它是纯虚函数
(2)const表明不能修改其数据成员
const 和 =0 没有关系,要分开理解   
 成员函数后面用 const 修饰,通俗的理解就是在这个函数内不能修改类的成员变量,除非那个成员变量是   mutable   的
  */

class B1:public B0
{
public:
	void display() const
	{
		cout <<  "我是显示页面B1" << endl;
		x = 0;
		/*error C2166: 左值指定 const 对象*/
	}
private:
	int x;
};


  • 7
    点赞
  • 14
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论
可以使用结构体来定义一个虚数,结构体中包含实数部分和虚数部分的变量。下面是一个例子: ```c #include <stdio.h> typedef struct { double real; double imag; } Complex; Complex add(Complex a, Complex b) { Complex c; c.real = a.real + b.real; c.imag = a.imag + b.imag; return c; } Complex sub(Complex a, Complex b) { Complex c; c.real = a.real - b.real; c.imag = a.imag - b.imag; return c; } Complex mul(Complex a, Complex b) { Complex c; c.real = a.real * b.real - a.imag * b.imag; c.imag = a.real * b.imag + a.imag * b.real; return c; } Complex div(Complex a, Complex b) { Complex c; double denominator = b.real * b.real + b.imag * b.imag; c.real = (a.real * b.real + a.imag * b.imag) / denominator; c.imag = (a.imag * b.real - a.real * b.imag) / denominator; return c; } int main() { Complex a = {1.0, 2.0}; Complex b = {3.0, 4.0}; Complex c = add(a, b); printf("add: %lf + %lfi\n", c.real, c.imag); c = sub(a, b); printf("sub: %lf + %lfi\n", c.real, c.imag); c = mul(a, b); printf("mul: %lf + %lfi\n", c.real, c.imag); c = div(a, b); printf("div: %lf + %lfi\n", c.real, c.imag); return 0; } ``` 这里定义了四个基本的运算函数,分别实现两个复数的加减乘除。在主函数中,定义了两个复数 a 和 b,并且调用了这四个运算函数,将结果打印出来。输出结果如下: ``` add: 4.000000 + 6.000000i sub: -2.000000 + -2.000000i mul: -5.000000 + 10.000000i div: 0.440000 + -0.080000i ``` 可以看到,程序成功地实现了虚数的计算。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

狂奔的乌龟

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值