04 继承与派生

继承与派生

目的:不影响原来的类,不改变原来类的代码,实现对于功能的扩展。

内容:基本概念 && 名词解释 语法实现 深入分析 菱形继承

继承与派生(名词解释)

继承:

一种在已有类的基础上创建新类的方式(类与类之间的关系);

新创建的类叫派生类子类——对应基类父类

继承与派生是同一过程的不同(角度)描述方式,站在子类角度,从父类继承过来,站在父类角度,派生出去。

继承分类:

  1. 单继承:只有一个父类(基类);
  2. 多继承:多个父类(基类)。

继承方式

语法

一、单继承

class 父类名
{
    
};

class 子类名 : 继承权限 父类名
{
    
};

二、多继承

class 父类名1
{
    
};

class 父类名2
{
    
};
……
class 子类名 : 继承权限 父类名1, 继承权限 父类名2... , 继承权限n 父类名n
{
    
};

三、继承权限

  1. 公有继承 public
  2. 私有继承 private
  3. 保护继承 protected

注意:

​ 继承是子类继承父类的全部成员(函数、数据),但是受访问权限限制。

权限授予

父类成员的访问权限\继承权限公有继承 public私有继承 private保护继承 protected
publicpublicprivateprotected
private不可访问不可访问不可访问
protectedprotectedprivateprotected

多级继承:通过父子关系的继承权限去分析。

举例:

#include <iostream>
using namespace std;

class Father
{
public:
	Father();
	~Father();
public:
	int pub;
	void pub_func();

private:
	int pri;
	void pri_func();
protected:
	int pro;
	void pro_func();
};


class Son : public Father
{
public:
	Son();
	~Son();
public:
	int num;
	void test_func()
	{
		this->num;
		// 公有权限可以访问
		this->pub;
		this->pub_func();
		// 保护权限在类的内部可以访问
		this->pro;
		this->pro_func();
	}
private:

};



int	main()
{
	cout << "sizeof(Father)" << sizeof(Father) << endl;
	cout << "sizeof(Son)" << sizeof(Son) << endl;
	Son obj_son;
	obj_son.pub_func();
	return 0;
}

Father::Father()
{
}

Father::~Father()
{
}

void Father::pub_func()
{
}

void Father::pri_func()
{
}

void Father::pro_func()
{
}


Son::Son()
{
}

Son::~Son()
{
}


父子关系

派生类的构成

构造和析构不会继承,其他成员可以被继承;

派生类的成员和基类成员的成员名相同时,基类的成员会被隐藏,需要使用基类的成员时,需在成员名前加基类类名+作用域符。

#include <iostream>
using namespace std;

class Father
{
public:
	Father();
	~Father();
public:
	int val;
	int num;
	
};

class Father_1
{
public:
	Father_1();
	~Father_1();

public:
	int val;

};

class Son : public Father, public Father_1
{
public:
	Son();
	~Son();
public:
	int num;

};


int	main()
{
	Son obj_son;
	cout << "obj_son.num = " << obj_son.num << endl;
	cout << "obj_son.Father::num = " << obj_son.Father::num << endl;
	/* 来自两个不同Father的同名成员 */
	cout << "obj_son.Father::val = " << obj_son.Father::val << endl;
	cout << "obj_son.Father_1::val = " << obj_son.Father_1::val << endl;

	return 0;
}
/* Father */
Father::Father()
{
	val = 10;
	num = 12;
}
Father::~Father()
{
	
}

/* Father_1 */
Father_1::Father_1()
{
	this->val = 1;
}

Father_1::~Father_1()
{
}

/* Son */
Son::Son()
{
	num = 99;
}

Son::~Son()
{
}


输出:

在这里插入图片描述

派生类和基类的关系

父类对象可以用子类对象赋值,子类对象不能用父类对象赋值(子类对象的范围比父类对象的范围大,父类对象无法赋慢)

父类指针可以指向子类对象,但子类指针不能指向父类对象(子类指针读取的内存范围比父类指针大)

#include <iostream>
using namespace std;

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

class Son : public Father
{
public:
	Son();
	~Son();


};

int	main()
{
	Father obj_fat;
	Son obj_son;

	Father* p_fat = NULL;
	Son* p_son = NULL;

	// 父类对象可以用子类对象赋值,子类对象不能用父类对象赋值(子类对象的范围比父类对象的范围大,父类对象无法赋慢)
	obj_fat = obj_son;
	// obj_son = obj_fat;

	// 父类指针可以指向子类对象,但子类指针不能指向父类对象(子类指针读取的内存范围比父类指针大)
	p_fat = &obj_son;
	// p_son = &obj_fat;

	return 0;
}

/* Father */
Father::Father()
{
	
}
Father::~Father()
{
	
}



/* Son */
Son::Son()
{
	
}

Son::~Son()
{
}


派生类构造和析构的顺序

在成员初始化列表可以调用构造函数,除此之外构造函数不能被主动调用。

#include <iostream>
using namespace std;

class Father
{
public:
	Father();
	Father(int n);
	~Father();
public:
	const int num;
	
};

class Son : public Father
{
public:
	Son();
	Son(int n, int v);
	~Son();
public:
	int val;
};

int	main()
{
	// Son obj_son;
	// Son obj_son(3, 4);
	Son obj_son(3, 4);
	cout << " obj_son.num = " << obj_son.num
		<< " obj_son.val = " << obj_son.val 
		<< endl;


	return 0;
}


/* Father */
Father::Father() : num(0)
{
	//num = 12;
	cout << "父类的构造" << endl;
}
Father::Father(int n) : num(n)
{
	//n = num;
	cout << "父类的带参构造" << endl;

}
Father::~Father()
{
	cout << "父类的析构" << endl;

}

/* Son */
Son::Son()
{
	val = 10;
	cout << "子类的构造" << endl;
}
// 在成员初始化列表可以调用构造函数,构造函数是不能被主动调用的。
Son::Son(int n, int v) : Father(n)
{	
	val = v;
	cout << "子类的带参构造" << endl;
}

Son::~Son()
{
	cout << "子类的析构" << endl;
}

输出:

在这里插入图片描述

菱形继承

类AA继承了两份来自类A的成员,多余了。

在这里插入图片描述

虚继承

解决多余继承(如菱形继承)的情况。

关键字:virtual

#include <iostream>
using namespace std;

class A
{
public:
	int n = 5;

};

class A_1 : virtual public A
{
public:
	int a1;
};

class A_2 : virtual public A
{
public:
	int a2;
};

class AA : public A_1, public A_2
{
public:
	int aa;
};





int	main()
{
	AA obj_aa;
	obj_aa.aa;
	obj_aa.a1;
	obj_aa.a2;
	// obj_aa.n;
	//cout << "obj_aa.A_1::n = " << obj_aa.A_1::n << endl;
	//cout << "obj_aa.A_2::n = " << obj_aa.A_2::n << endl;
	//cout << "obj_aa.A::n = " << obj_aa.A::n << endl;

	
	cout << "sizeof(A_1) = " << sizeof(A_1) << endl;
	cout << "sizeof(A_2) = " << sizeof(A_2) << endl;
	cout << "sizeof(AA) = " << sizeof(AA) << endl;

	cout << "sizeof(A*) = " << sizeof(A*) << endl;
	cout << "sizeof(A_1*) = " << sizeof(A_1*) << endl;
	cout << "sizeof(A_2*) = " << sizeof(A_2*) << endl;

	cout << "sizeof(int) = " << sizeof(int) << endl;


	return 0;
}


<未完待续>

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值