c++类——继承(一)

如有兴趣了解更多请关注我的个人博客https://07xiaohei.com/

(一)概念:

继承机制是面向对象程序设计中最重要的一个概念,也是使代码可以复用的最重要的手段。

继承机制允许我们依据一个类来定义另一个类,它允许程序员在保持原有类特性的基础上进行扩展,增加功能,能使对类的创建和维护更加容易——能够重用代码功能和提高执行效率。

被继承的类,也就是已有的类,被称为基类(父类),而发生继承的类,也就是新建的类,被称为派生类(子类)。

如果要使用基类的成员,派生类不需要重新编写新的数据成员和成员函数,只需要指定继承的已有的类的成员。但是,派生类不能继承基类的构造函数、析构函数、拷贝构造函数、重载运算符和友元函数。

一个基类可以派生出多个派生类,一个派生类也可以从多个基类中继承数据成员和成员函数。

派生类只能访问基类的非私有成员。

(二)继承的语法形式:

class 派生类名:基类名表

{

数据成员和成员函数声明

};

其中,基类和一般情况下声明的类基本相同。

基类名表的组成为:

访问控制 基类名1 , 访问控制 基类名2 , …

访问控制是关键字,表示派生类对基类的继承方式。

#include<iostream>
using namespace std;
class person
{
};
class animal
{
};
class knowledge{};
class student :public animal,protected person,private knowledge
{
};
class teacher:public animal, protected person, private knowledge
{
};

(三)继承的三种方式:

访问控制的关键字共有三个,分别为public、private和protected。

如果未直接指定访问控制关键字,默认为private。

访问控制决定了不同的访问权限和访问类型,详细情况见下表。

可以看到,对于基类成员,派生类的继承如下:

- 基类的私有成员,派生类不可以访问

- 基类的保护成员,派生类可以继承为自己的保护成员(protected继承)和私有成员(private继承),在派生类可以访问,在外部不可以访问。

- 基类的公有成员,子类可以继承为自己的公有成员(public继承),保护成员(protected继承)和私有成员(private继承)。在派生类可以访问,在外部也可以访问。

对于派生类,公有继承保持基类的保护成员和公有成员不变;保护继承将基类的公有和保护成员变为保护成员;私有继承则将公有和保护成员变为私有成员。

注意:通过派生类可以初始化基类的私有数据成员,方式是通过调用基类的构造函数来实现对私有数据成员的初始化。

注意:虽然基类的私有数据成员不能在派生类中直接访问,但是派生类的对象也会为其建立私有的数据空间,所有继承时即使基类数据成员均为私有,也会导致派生类的占用空间很大。

#include<iostream>
using namespace std;
class Axy //基类
{
private:
	string Aname;
protected:
	double x;
	double y;
public:
	Axy(double d1 = 0, double d2 = 0,string s = "pointA" ):Aname(s),x(d1),y(d2){ }
	double getx() { return x; }
	double gety() { return y; }
	string getAname() { return Aname; }
};
class Bxy :public Axy //公有继承A,除了不能继承Aname,其余保持不变,构造函数不继承需要重新写
{
private:
	string Bname;
public:
	//对基类的一种初始化方式
	Bxy(double d1 = 0, double d2 = 0, string s1 = "pointB",string s2 ="pointA") :Bname(s1), Axy(d1, d2, s2) {}
};
class Cxy:protected Axy //保护继承A,不能继承Aname,其他均变为protected类型,构造函数不继承需要重新写
{
private:
	string Cname;
public:
	Cxy(double d1 = 0, double d2 = 0, string s1 = "pointC") :Cname(s1)
	{
		//继承可以直接使用基类的非私有数据成员
		x = d1;
		y = d2;
	}
	void use_A_function()
	{
		//继承可以使用基类的非私有成员函数
		cout << getx() << endl;
		cout << gety() << endl;
		return;
	}
	void use_A_function2()
	{
		cout << x << endl;
		cout << y << endl;
		return;
	}
};
class Dxy:private Cxy //私有继承C,不能继承Cname,其他均变为private类型,构造函数不继承需要重新写
{
private:
	string Dname;
public:
	Dxy(double d1 = 0, double d2 = 0, string s = "pointD") :Dname(s), Cxy(d1, d2) {}
};
class Exy :public Dxy //保护继承D,因为上面均变为private类型,所以什么都都没继承,只能对其构造和析构
{
private:
	string Dname;
public:
	Exy(double d1 = 0, double d2 = 0, string s = "pointD") :Dname(s), Dxy(d1, d2) {}
};
int main() 
{
	Bxy b(1,1,"bbb","aaa");
	cout << "b:" << b.getx() << "," << b.gety() << endl; //调用A的成员函数处理B的数据成员
	cout << "Aname:" << b.getAname() << endl;
	Cxy c; //c为保护继承,类外均不能调用原有的成员函数
	c.use_A_function();  //通过调用C的成员函数调用A的成员函数处理C的数据成员
	c.use_A_function2(); //调用C的成员函数对C的数据成员操作
	Dxy d; //d为私有继承,类外均不能调用原有的成员函数
	Exy e; //e为公有继承,但什么都没继承到,所以没有可以调用的成员函数。
	cout << sizeof(Axy) << endl;
	cout << sizeof(Bxy) << endl;
	cout << sizeof(Cxy) << endl;
	cout << sizeof(Dxy) << endl;
	cout << sizeof(Exy) << endl;
	return 0;
}
//运行结果:
//b:1, 1
//Aname : aaa
//0
//0
//0
//0
//56
//96
//96
//136
//176

(四)重名成员:

  • 同名也称为隐藏,派生类定义了与基类同名的成员时,派生类的同名成员会屏蔽掉基类的同名成员——子类优先。
  • 如果要使用基类的同名成员,需要显式地使用类名限定符。
  • 对于成员函数,同名的要求是函数名相同,对参数列表没有要求。
  • 注意基类和派生类的作用域是独立的(表现为各有自己的this指针),但是基类的作用域被延伸到了派生类中(也就是在派生类的作用域中可以调用基类的作用域)。
#include<iostream>
using namespace std;
class Axy
{
private:
	string Aname;
protected:
	double x;
	double y;
public:
	Axy(double d1 = 0, double d2 = 0,string s = "pointA" ):Aname(s),x(d1),y(d2){ }
	double getx() { return x; }
	double gety() { return y; }
	string getAname() { return Aname; }
};
class Bxy :public Axy
{
private:
	string Bname;
protected:
	double x;
	double y;
public:
	Bxy(double d1 = 0, double d2 = 0, double d3=0,double d4=0,string s1 = "pointB",string s2 ="pointA"):x(d1),y(d2),Bname(s1), Axy(d3, d4, s2) {}
	double getx() { return x; } //访问默认的子类的同名变量x
	double gety() { return y; } //访问默认的子类的同名变量y
	double getAx() { return Axy::x; } //访问基类的同名变量x
	double getAy() { return Axy::y; } //访问基类的同名变量y
	string getAname() { return Axy::getAname(); } //调用基类的成员函数getAname,这里绝对不能不加作用域,否则会陷入死循环。
	string getBname() { return Bname; }
};

int main()
{
	Bxy b;
	cout << "b:" << b.getx() << "," << b.gety() << endl;
	cout << "a:" << b.getAx() << "," << b.getAy() << endl;
	cout << "a:" << b.Axy::getx() << "," << b.Axy::gety() << endl;
	cout << "bname:" << b.getBname() << endl;
	cout << "aname:" << b.getAname() << endl;
	cout << "aname:" << b.Axy::getAname() << endl;
	return 0;
}
//运行结果:
//b:0, 0
//a : 0, 0
//a : 0, 0
//bname : pointB
//aname : pointA
//aname : pointA

(五)派生类访问静态成员:

  • 基类定义的静态成员将被所有派生类共享。
  • 根据静态成员自身的访问特性和派生类的继承方式,类层次体系中有不同的访问性质。
  • 派生类中访问静态成员,用以下形式显式说明:
    • 类名::成员
    • 对象名.成员
#include<iostream>
using namespace std;
class A
{
public:
	static int i;
	static void add_i()
	{
		i++;
		return;
	}
	void print() { cout << "i:" << i << endl; }
};
int A::i = 0;
class B:protected A
{
public:
	void add_i2() 
	{
		i++;
		return;
	}
};

int main()
{
	A a;
	B b;
	a.i++;
	a.add_i();
	b.add_i2();
	//b.A::add_i(); protect继承不能在类外访问A的成员
	//B::A::add_i(); 这样也不行
	A::i++;
	A::add_i();
	a.print();
	return 0;
}
//运行结果:
//i:5
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

打赏作者

xiaohei07

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

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

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

打赏作者

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

抵扣说明:

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

余额充值