C++ 类之间的关系(继承,组合,依赖,关联,聚合)

横向

组合

组合是一个类中包含另一个类对象, 组合关系的两个对象往往具有相同的生命周期,被组合的对象是在 组合对象创建的同时或者创建之后创建,在组合对象销毁之前销毁, 被组合对象不能脱离组 合对象独立存在。例如:人和心脏。

依赖

一个对象的某种行为依赖于另一个类对象, 只有在完成某个功能的时候才会用到,而且是必不可少的, 依赖之间是没有生命周期约束关系。例如:人和手机。

关联

完成 某个功能与被关联的对象有关,但是可有可无,被关联的对象与关联的对象无生命周期约束关系,被 关联对象的生命周期由谁创建就由谁来维护,被关联的对象还可以再被别的对象关联,所以关联是可以共享的。例如:人和朋友。

聚合

多个被聚合的对象聚集起来形成一个大的整体,聚合的目的是为了统一进行管理同类型的对象,聚合是一种弱所属关系,被聚合的对象还可以再被别的对象关联,所以被聚合对象是可以共享的,比关联关系更紧密。例如:一群学生一些老师组成一个班级。

纵向

继承

被继承的类叫做基类(父类),继承的类叫派生类(子类),在派生类类名后面加 : 继承方式 基类
class CFather{};
class CSon:public CFather{};
通过继承关系,子类可以使用父类的成员。如果子类和父类有同名的成员,默认使用子类的成员,如果想要使用父类的成员,需要在成员名前加上 类名:: 用于显式的指定区分, 子类继承父类,相当于将父类的成员包含到自己的类里,所以定义 子类对象所占用的空间大小除了子类自身的成员还包括父类的成员 成员在内存空间分布为:先父类成员后子类成员,而每个类中的成员分布与在类中声明的顺序一致。
class CFather{
public:
    int m_a;
};
class CSon:public CFather{
public:
    int m_a;
};

int main(){
    Cson son;
    son.m_a;            //子类成员
    son.CSon::m_a;      //子类成员
    son.CFather::m_a;   //父类成员

    return 0;

}

继承构造析构顺序:

定义子类对象时执行顺序:父构造->子构造->孙构造...| ...孙析构->子析构->父析构

构造顺序:在子类创建对象的时候,调用子类的构造函数(注意这里并不是直接先执行父类的构 造函数),但要先执行构造的初始化列表,在初始化列表中会默认调用父类的无参构造初始化父类成员, 如父类只有带参数的构造,在子类的初始化参数列表中必须显式的指定父类构造进行初始化 。这有点像之前说的组合关系形式。
析构顺序:子类对象的生命周期结束后,因为是子类所以自动调用子类析构,当析构执行完了,才会回收对象分配的空间,当然这个空间包含创建的父类的成员,那么回收父类成员前,自动调用父类的析构。如果是new 出来的子类对象,同理。
继承方式:
三种继承方式 public protected private
继承方式与访问修饰符共同决定了父类成员在子类中所表现的属性
隐藏:

对于父类和子类,如果有同名的函数但是参数列表不同,则不能够自动区分匹配,因为他们之间 的关系并不是函数重载的关系,作用域不同,必须使用 类名:: 去区分到底该调用哪个函数。这种关系一般称之为 隐藏子类对象调用时默认走自己的那个

class CFather {
public:
void fun();
};
class CSon :public CFather {
public:
void fun(int a); //隐藏关系,自动将父类的成员屏蔽了
};
父类的指针指向子类的对象:
继承关系下,允许父类的指针指向子类的对象,但是反过来却不行。 好处是:父类的指针可以统一多个类的类型,提高代码的复用性、扩展性。父类的指针只能使用父类的成员,不能使用子类的成员。
CFather * p = new CSon;
CSheep,CDog,CPig都继承Cpet可以通过父类指针统一管理三种子类对象,减少了代码量。
class CPet
{
public:
	int m_weight;
	void walk()
	{
		cout << "散步" << endl;
	}
	CPet()
	{
		m_weight = 20;
	}
};
class CSheep:public CPet
{
public:
	void like()
	{
		cout << "喜欢吃草" << endl;
	}
};
class CPig :public CPet
{
public:
	void like()
	{
		cout << "喜欢胡萝卜" << endl;
	}
};
class CDog :public CPet
{
public:
	void like()
	{
		cout << "喜欢骨头" << endl;
	}
};

//父类的指针可以统一多种子类类型,减少代码的冗余,提高程序复用性、扩展性
void fun(CPet *pCPet)		
{
	cout <<"体重: " << pCPet->m_weight << endl;
	//pCPet->like();	//父类的指针只能使用父类的成员,不能使用子类的成员    
	pCPet->walk();
}

int main()
{
	fun(new CSheep);
	fun(new CPig);
	fun(new CDog);
	return 0;
}
继承优点:
可以将类中的一些功能相近、相似的共同的方法,抽离出来放到单独的一个类中,并让其继承这个类,那么抽离出来的类就是父类,将来其他类在增加公共的方法时,我只需要在父类添加一份即可。提高了代码的复用性、扩展性
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值