C++知识点44——类的继承概述

类的继承,是新类从已有类那里得到已有的特性,或从已有类产生新类的过程。原有类称为基类或父类,新类称为派生类或子类

子类通过类派生列表确定子类继承了哪些类。类派生列表的形式如下

class 子类名:访问说明符 基类1名, 访问说明符 基类2名, 访问说明符, 基类3名 {
    //...
}

示例

class base1
{
public:
	base1(){}
	~base1(){}
	
};

class base2
{
public:
	base2(){}
	~base2(){}
	
};

class base3
{
public:
	base3(){}
	~base3(){}
	
};

class derive:public base2
{
public:
	derive(){}
	~derive(){}
	
};

class derive1:public base1, protected base2, private base3
{
public:
	derive1(){}
	~derive1(){}
	
};

上述代码表明:C++既有单一继承,也有多重继承,而且继承也可以分为公有继承,保护继承和私有继承

 

一、子类会继承父类的哪些成员

当一个子类继承父类时,父类中的所有非static成员函数和成员变量会被子类全部继承,但是子类不一定能够访问到全部的非static成员

示例

class base2
{
public:
	base2(){cout<<__func__<<endl;}
	~base2(){cout<<__func__<<endl;}
	void func2() {cout<<__func__<<endl;
		func2pri();
	}
	int a;

protected:
	void func2pro() {cout<<__func__<<endl;}
	int b;

private:
	void func2pri() {cout<<__func__<<endl;}
	int c;
};


class derive:public base2
{
public:
	derive(){cout<<__func__<<endl;func2pro();/*func2pri();*/}
	~derive(){cout<<__func__<<endl;}
	//void func2() {cout<<"func2 in base3"<<endl;}
};

int main(int argc, char const *argv[])
{
	derive t;
 cout<<sizeof(t)<<endl;
	t.func2();
	cout<<t.a<<endl;
	//t.func2pro();
	return 0;
}

输出结果表明:

1、当一个子类被创建时,先分配存储空间(即从基类继承下来的数据大小加上子类自身数据成员的大小)。然后调用基类的构造函数来初始化从基类继承下来的数据。,接着调用子类的构造函数来初始化子类中的数据成员。此时,子类对象创建完成。子类的sizeof是12,说明父类中的数据都被子类继承了

2、protected成员可以在子类中被访问,但是不能在其他类中或者其他作用域中被访问,如果将主函数中的t.func2pro();的注释解除,会出现如下错误

提示父类中的func2pro是protected。不能在main函数中被访问

3、即使子类继承了父类的private成员,但是依旧不能访问父类的private成员,如果将第31行的func2pri();注释解除,则会出现以下错误

提示父类中的func2pri是private,只能在类内被访问

4、如果在子类中实现一个和父类的同名函数,那么会优先调用子类的同名函数,不会调用父类的同名函数,如果将第33行的void func2() {cout<<"func2 in base3"<<endl;}注释解除,则会出现以下输出结果

5.当一个子类被销毁时,会先调用子类的构造函数,将子类对象中子类的成员销毁,然后再调用父类的构造函数,将子类对象中父类对应的成员销毁,此时,子类对象被完全销毁

所以,子类对象创建时,会从对应的基类部分到子类部分一步一步创建,销毁时,也会从对应的子类部分到基类部分一步一步销毁;子类即使继承了父类的所有非static成员,但是子类并不能访问所有的非static成员。子类调用一个成员时,会现在子类对应的部分查找是否有对应的成员,如果有,直接调用,如果没有,会继续到父类中继续查找,如果有,调用父类对应的成员,否则报错

 

二、protected关键字

该关键字就是为继承而生的。子类能够访问父类的公有成员,不能访问父类的私有成员,但是C++还希望父类的有些成员只有子类能访问,其他类或者作用域不能访问,所以protected产生了

 

三、类的继承与static成员

如果基类中定义了static成员,那么,无论基类有多少个子类,每个static成员都只有一个实例

示例

class base1
{
public:
	base1(){}
	~base1(){}
	static void sfunc() {cout<<__func__<<endl;}
	static int st;
};

int base1::st=10;

class derive2:public base1
{
public:
	derive2(){cout<<__func__<<endl;}
	~derive2(){cout<<__func__<<endl;}
	
};

int main(int argc, char const *argv[])
{
	derive2 t;
	t.sfunc();
	cout<<t.st<<endl;
	derive2::sfunc();
	base1::sfunc();
	cout<<&derive2::st<<endl;
	cout<<&base1::st<<endl;

	return 0;
}

static成员既可以通过基类来访问,也可以通过子类来访问,而且打印出的地址都是相同的,这都是因为static成员在继承体系中只有一个实例,无论有多少个子类,static成员都是共享的

 

四、什么样的类可以被当做基类

如果一个类可以被作为基类,那么该类必须已经定义,而不是仅仅声明;一个仅仅被声明而没有被定义的类不能做父类

示例

class base4;
class derive3:public base4
{
public:
	derive3();
	~derive3();
	
};

因为子类要从基类中获得成员,而一个类仅仅声明,没有实现,那么子类就无法知道基类中到底有啥,所以提示基类不完整。因为类在定义的过程中也是不完整的,所以一个类不能继承它本身

 

五、如何防止继承

如果不想让一个类当父类,可以在类名后加个关键字final

class base3 final
{
public:
	base3(){}
	~base3(){}
};

class derive3:public base3
{
public:
	derive3();
	~derive3();	
};

 

参考

《C++ Primer》

 

欢迎大家评论交流,作者水平有限,如有错误,欢迎指出

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值