2021-02-04仅供自己参考:继承

继承基本语法

继承好处:减少重复代码
class 子类 : 继承方式 父类
子类也称派生类
父类也称基类
派生类的成员包括了自己本身的成员(特有属性),
还包括了从基类继承的成员(共有属性)。

#include<iostream>
#include<string>
using namespace std;

class A
{

public:
	void f1()
	{
		cout << "f1" << endl;
	}
	void f2()
	{
		cout << "f2" << endl;
	}
	void f3()
	{
		cout << "f3" << endl;
	}
};
class B:public A
{
public:
	void F1()
	{
		cout << "F1" << endl;
	}
};

void t1()
{
	A a;
	cout << "A" << endl;
	a.f1();
	a.f2();
	a.f3();
	B b;
	cout << "B" << endl;
	b.f1();
	b.f2();
	b.f3();
	b.F1();
}

int main()
{
	t1();
	system("pause");
	return 0;
}

继承方式

继承方式有三种:

  • 公共继承
  • 保护继承
  • 私有继承
    公共继承:父类的公共权限在子类中仍然是公共权限,父类的保护权限在子类中仍是保护权限,父类的私有权限不能访问。
class A
{
public:
	int a;
protected:
	int b;
private:
	int c;
};
class B:public A
{
public:
	int a;
protected:
	int b;
	//private:int c 不能访问
};

保护继承:父类的公共权限和保护权限在子类中都变为保护权限,父类的私有权限不能访问。

class A
{
public:
	int a;
protected:
	int b;
private:
	int c;
};
class B:public A
{
protected://类外不能访问
	int a;
	int b;
	//private:int c 不能访问
};

私有权限:父类的公共权限和保护权限在子类都变成私有权限,父类的私有权限不能访问。

class A
{
public:
	int a;
protected:
	int b;
private:
	int c;
};
class B:public A
{
	private://类外不能访问
		int a;
		int b;
		//int c 不能访问
};

继承中的对象模型

父类的私有成员也会被继承下去,只是被隐藏了。


#include<iostream>
#include<string>
using namespace std;
class A
{
public:
	int a;
protected:
	int b;
private:
	int c;//同样继承下去,只是被隐藏了
};
class B:public A
{
public:
	int d;
};
void t1()
{
	cout << "sizeof(B)=" << sizeof(B)<<endl;
}
int main()
{
	t1();
	system("pause");
	return 0;
}

在这里插入图片描述

构造与析构顺序

父类先构造然后子类再构造,
子类先析构然后父类再析构。

#include<iostream>
#include<string>
using namespace std;
class A
{
public:
	A()
	{
		cout << "父类构造函数" << endl;
	}
	~A()
	{
		cout << "父类析构函数" << endl;
	}
};
class B :public A
{
public:
	B()
	{
		cout << "子类构造函数" << endl;
	}
	~B()
	{
		cout << "子类析构函数" << endl;
	}
};
void t1()
{
	B p;
}
int main()
{
	t1();
	system("pause");
	return 0;
}



在这里插入图片描述

同名成员的处理

  • 访问子类同名成员直接访问即可
  • 访问父类同名成员需要加作用域


    如果子类中出现和父类同名的成员函数,子类的同名成员会隐藏掉父类中所有同名成员函数。想访问到父类中被隐藏的同名成员函数,需要加作用域。
#include<iostream>
#include<string>
using namespace std;

class A
{
public:
	A()
	{
		a = 1;
	}
	void f()
	{
		cout << "父类函数调用" << endl;
	}
	void f(int a)
	{
		cout << "父类函数调用01" << endl;
	}
	int a;
};

class B :public A
{
public:
	B()
	{
		a = 2;
		
	}
	void f()
	{
		cout << "子类函数调用" << endl;
	}
	int a;
};

void t1()
{
	B p;
	cout << "p.a=" << p.a << endl;//访问子类中的a
	cout << "p.A::a=" << p.A::a << endl;//父类中的a
	//从子类对象访问父类中的同名成员需要加作用域
	p.f();
	p.A::f();//子类访问父类中同名成员函数需要加作用域
	//p.f(1)如果子类中出现和父类同名的成员函数,
	//子类的同名成员会隐藏掉父类中所有同名成员函数
	p.A::f(1);//如果想访问到父类中被隐藏的同名成员函数,需要加作用域
}

int main()
{
	t1();
	system("pause");
	return 0;
}



继承同名静态成员的处理

静态成员和非静态成员出现同名,处理方式一致
访问子类同名成员直接访问即可
访问父类同名成员需要加作用域

#include<iostream>
#include<string>
using namespace std;

class A
{
public:
	
	static void f()
	{
		cout << "父类静态函数调用" << endl;
	}
	static void f(int a)
	{
		cout << "父类静态有参函数调用" << endl;
	}
	static int a;
};
int A::a = 1;//类外初始化
class B :public A
{
public:
	
	static void f()
	{
		cout << "子类静态函数调用" << endl;
	}
	static int a;
};
int B::a = 2;//类外初始化
void t1()
{
	B p;
	cout << endl<<"通过对象访问静态成员" << endl;
	cout << "p.a=" << p.a << endl;//访问子类中的a
	cout << "p.A::a=" << p.A::a << endl;//父类中的a
	cout << endl<<"通过类名访问静态成员" << endl;
	cout << "B::a=" << B::a << endl;
	cout << "B::A::a=" << B::A::a << endl;//第一个::表示通过类名的方式访问数据
	                                      //第二个::表示访问父类作用域下的a

}
void t2()
{
	//通过对象访问
	cout << endl<<"通过对象访问静态成员函数" << endl;
	B p;
	p.f();
	p.A::f();
	//通过类名访问
	cout << endl<<"通过类名访问静态成员函数" << endl;
	B::f();
	B::A::f();
	cout << endl<<"通过类名访问父类同名静态有参成员函数" << endl;
	B::A::f(1);
	//子类出现和父类同名静态成员函数,也会隐藏父类中所有同名成员函数
	//如果想访问父类中被隐藏同名成员,需要加作用域
}

int main()
{
	t1();
	t2();
	system("pause");
	return 0;
}



在这里插入图片描述

继承语法

C++允许一个类继承多个类
语法:
class 子类 : 继承方式 父类1,继承方式 父类2……

多继承可能会引发父类中有同名成员出现,需要加作用域区分

注意:加了final的类不能作为父类

class A final
{
}
class B :public A//错误,A类不能作为父类
{
}
#include<iostream>
#include<string>
using namespace std;

class A
{
public:
	A()
	{
		a = 1;
	}
	int a;
};
class B 
{
public:
	B()
	{
		a = 2;
	}
	int a;
};
class C :public A, public B
{
public:
	C()
	{
		c = 3;
		d = 4;
	}
	int c;
	int d;
};
void t1()
{
	C p;
	cout << "sizeof(p)=" << sizeof(p)<<endl;
	cout << "p.A::a=" << p.A::a << endl;//父类中有同名成员要加作用域
	cout << "p.B::a=" << p.B::a << endl;
}
int main()
{
	t1();
	system("pause");
	return 0;
}



在这里插入图片描述

菱形继承问题及其解决方法

菱形继承概念:
两个派生类继承同一个基类,又有某个类同时继承者两个派生类。
这种继承被称为菱形继承,或者钻石继承。
在这里插入图片描述
菱形继承问题:
1.B继承了A的数据,C同样继承了A的数据,当D使用数据时,就会产生二义性。
2.D继承自A的数据继承了两份,其实我们应该清楚,这份数据我们只需要一份就可以。

利用虚继承解决菱形继承的问题
继承之前加上关键字virtual变为虚继承
A类称为虚基类(最大的类)
继承了两个指针,指针通过偏移量找到唯一的数据

#include<iostream>
#include<string>
using namespace std;
class A
{
public:
	A()
	{
		a = 1;
	}
	int a;
};
class B :virtual public A
{
public:
};
class C :virtual public A
{
public:
};
class D :public B, public C
{
public:
};
void t1()
{
	D p;
	p.B::a = 2;
	p.C::a = 3;//虚继承使数据只有一份。
	//当菱形继承,两个父类拥有相同数据,需要加以作用域区分
	cout << "p.B::a=" << p.B::a << endl;
	cout << "p.C::a=" << p.C::a << endl;
	//只要有一份就可以,菱形继承导致数据有两份,资源浪费
	cout << "p.a=" << p.a << endl;
}
int main()
{
	t1();
	system("pause");
	return 0;
}



在这里插入图片描述

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值