C++(2):virtual、explicit和template

C++继承

通过继承机制,可以利用已有的数据类型来定义新的数据类型。所定义的新的数据类型不仅拥有新定义的成员,而且还同时拥有旧的成员。我们称已存在的用来派生新类的类为基类,又称为父类。由已存在的类派生出的新类称为派生类,又称为子类。
C++继承分为三类:
公有继承
基类的公共成员和受保护成员在派生类中访问属性还是不变,在派生类中,只有基类的私有成员在派生类中不可直接访问
即派生类的访问权限:public不变、private不可见、protected不变。
私有继承
基类的公用成员和保护成员都以私人身份出现在派生类中,派生类中的其他成员可以直接访问基类的公共和保护成员
即派生类的访问权限:public和protected变为private
保护继承
基类的公用成员和保护成员都以保护身份出现在派生类中。
即派生类访问权限:public变成protected、protected不变
举个例子:比如在之前引入联合体的学校信息管理系统,在学校信息分为职工信息和学生信息,两者信息有相同的部分,也有不同的部分,我们把相同的部分作为基类,把两者不同的部分作为两个不同的派生类,这样就可以满足两种需求。

class information
{
public:
 information(char a, char b, int c)
 {
  name = a;
  sex = b;
  age = c;
 }
protected:
 char name;
 char sex;
 int age;
};
class student :public information
{
public:
 student(char a, char b, int c, int d, char e) :information(a, b, c)
 {
  stu_number = d;
  college = e;
 }
protected:
 int stu_number;
 char college;
};
class teacher :public information
{
public:
 teacher(char a, char b, int c, int d, char e,char f) :information(a, b, c)
 {
  tea_number = d;
  rank = e;
  college = f;
 }
protected:
 int tea_number;
 char rank;
 char college;
};
int main()
{
 student stu1('w', '男', 21, 123456, '计科');
 teacher tea1('w', '男', 21, 123456, '教授', '计科');
 return 0;
}

virtual

virtual主要用在两个方面:虚函数与虚基类。

虚函数

虚拟函数就是为了对“如果你以一个基础类指针指向一个衍生类对象,那么通过该指针,你只能访问基础类定义的成员函数”这条规则反其道而行之的设计。

class information
{
public:
	information()
	{

	}
	information(char a, char b, int c)
	{
		name = a;
		sex = b;
		age = c;
	}
	void fun()
	{
		printf("is information");
	}
protected:
	char name;
	char sex;
	int age;
};
class student :public information
{
public:
	student()
	{

	}
	student(char a, char b, int c, int d, char e) :information(a, b, c)
	{
		stu_number = d;
		college = e;
	}
	void fun()
	{
		printf("is student");
	}
protected:
	int stu_number;
	char college;
};
int main()
{
	information *p1 = new information;
	information *p2 = new student;
	p1->fun();
	p2->fun();
	return 0;
}

输出结果如下
在这里插入图片描述
两次函数调用都调用的是基类中的fun函数
在基类的fun函数前加上virtual输入结果为
在这里插入图片描述
即基类指针可以调用派生类的成员函数
注意:
1.在c++中的继承中,如果基类声明了一个函数为虚函数,那么在派生类中不用声明同名函数为虚函数(不需要加virtual)也可以实现该函数为虚函数
2.基类中的析构函数必须为虚函数,否则会出现对象释放错误。以上例说明,如果不将基类的析构函数声明为virtual,那么在调用delete p2;语句时将调用基类的析构函数,而不是应当调用的派生类的析构函数,从而出现对象释放错误的问题。
3.重写函数的特征标必须与基类函数一致,否则将覆盖基类函数;
4.重写不同于重载。我对重载的理解是:同一个类,内部的同名函数具有不同的参数列表称为重载;重写则是派生类对基类同名函数的“本地改造”,要求函数特征标完全相同。当然,返回值类型不一定相同。
5.虚函数调用的原理:编译器给每一个包括虚函数的对象添加了一个隐藏成员:指向虚函数表的指针(敲黑板,后面会用)

虚基类

在c++中,派生类可以继承多个基类。如果这多个基类又是继承自同一个基类时,那么派生类是不是需要多次继承基类中的内容?由此引入虚基类

class mate
{
public:
	mate()
	{
	}
	virtual ~mate()
	{
	}

protected:
	int a;
	int b;
};
class mate1 :virtual public mate
{
public:
	mate1()
	{}
protected:
	int c;

};
class mate2 :virtual public mate
{
public:
	mate2()
	{}
protected:
	int d;
};
class mate3 :public mate1, public mate2
{
public:
	mate3()
	{}
protected:
	int e;
};
int main()
{
	cout << sizeof(mate) << endl;
	cout << sizeof(mate1) << endl;
	cout << sizeof(mate2) << endl;
	cout << sizeof(mate3) << endl;
	return 0;
}

程序的运行结果是什么呢?
在这里插入图片描述
现在问题来了mate的大小为什么是12呢?
上面说过虚函数在调用时编译器会增加一个指向虚函数表的指针,大小为4字节,加上两个整形指针变量一共是12个字节。
再看mate1和mate2,每个派生类增加了一个整形变量,但是大小却增加了8个字节。这是因为它们在虚继承自mate类后,添加了一个隐藏的成员——指向虚基类的指针,占4个字节。
这样mate3 = 12 + 8 + 8 + 4 = 32个字节。

explicit

explicit关键字只能用于修饰只有一个参数的类构造函数, 它的作用是表明该构造函数是显示的, 而非隐式的, 跟它相对应的另一个关键字是implicit, 意思是隐藏的,类构造函数默认情况下即声明为implicit(隐式).
explicit关键字的作用就是防止类构造函数的隐式自动转换.
举个例子,

class stu{
public:
explicit stu(int i)
{
	a = i;
}
};
int main()
{
	stu p1(10); //可以赋值
	stu p2 = 10; //出现错误,存在类型的隐式转换 10被转换为一个临时的stu对象
	return 0;
}

template

C++的模板设施提供了一种机制,它能够将类函数定义内部的类型和值参数化。这些参数作为占位符,以后会绑定到实际类型上。以数组为例:

template <class type>
class Array {
	explicit Array(int size = DefaultArraySize);
	Array(type *array, int array size);
	Array(const Array &rhs);
	virtual ~Array()
	{
		delete[] p1;
	}
	bool operator==(const Array&)const
	{}
	bool operator!=(const Array&)const
	{}
private:
	static const int DefaultArrayize = 12;
	int _size;
	type *p1;
};

关键字template引入模板,参数由一堆尖括号括起来,有一个参数type。关键字class表明这个参数代表一个类型。标识符type代表实际参数名。

  • 1
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值