Day 8 C++继承和派生

一、继承方式和权限问题:

父类(继承中) 基类(派生)->子类 派生类

实质:父类的数据成员子类中也有一份。

注:父类的私有属性能够被子类继承下来,但是不可以直接被访问(即通过接口访问是可以的,在父类中写一个接口函数)

写法:

class parent{};
class 子类名 : 继承方式 父类名{}

其中的继承方式就是 三种权限限定。

权限问题:继承方式只会增强父类属性在子类中的权限显示。

(以下表格默认是直接访问)

注意:最后一行,private是在子类中的私有,在子类中,仍可以直接访问。而“不可直接访问”是父类的私有,无论何时都不可以直接访问(私有继承容易“断了血脉”,因为再继承无法再有任何作用)。

二、继承中的构造函数:

父类的属性需要通过父类的构造函数去初始化。

②子类中的构造函数,必须调用父类构造函数(注意区分类的组合的写法(初始化列表用的是对象名),此处直接用类名),必须采用初始化参数列表的方式(这是子类,父类爱咋写咋写)

         注:1.子类构造对象,优先调用父类构造函数。

                2.Son(){ }这种写法,父类必须存在无参的构造函数,当然缺省也可以。

③单继承和多继承

        1.单继承:只有一个父类

         2.多继承(吕布):两个or两个以上的父类

例:“阳子”与“欧田”

#include<iostream>
#include<string>

using namespace std;

class a
{
public:
	a(string mmFname,string mmSname):mmFname(mmFname), mmSname(mmSname){}
protected:
	string mmFname;
	string mmSname;
};
class b
{
public:
	b(string mmFname, string mmSname) :ggFname(mmFname), ggSname(mmSname) {}
protected:
	string ggFname;
	string ggSname;
};
class daughter:public a,public b
{
public:
	daughter(string mmFname, string mmSname, string ggFname, string ggSname) :a(mmFname, mmSname), b(ggFname, ggSname)
	{
		daFname = mmFname + ggFname;
		daSname = mmSname + ggSname;
	}
	void print()
	{
		cout << "妈妈:" + mmFname + mmSname << endl;
		cout << "爸爸:" + ggFname + ggSname << endl;
		cout << "女儿:" + daFname + daSname << endl;
	}
protected:
	string daFname;
	string daSname;
};

int main()
{
	daughter wbm("阳", "子", "欧", "田");
	wbm.print();
	return 0;
}

 ④继承的属性,无论被继承多少次一直都是在的,所以类一般不会被继承很多层(3),会导致类的臃肿。

三、继承中同名问题:

1.数据成员同名、成员函数同名以及正常的赋值指针调用:不做特殊处理,遵循就近原则

(子类中print子类数据成员)

想调用远的?解决:加上类名限定::

2.非正常指针:①允许子类对象初始化父类指针

  MM* pMM=new girl("newgirl",19);
  pMM->print();
//MM是父类 girl是子类                      

无virtual,看指针类型。

有virtual,看赋值对象 

(即若girl在继承的时候没有写 virtual public MM,那么这边同名就调用的是指针类型pMM的print(),若写了virtual,则是girl的print())

无virtual

#include<iostream>

using namespace std;

class A
{
public:
	A(int a,int b):a(a),b(b) {}
	void print()
	{
		cout << a << endl;
	}
protected:
	int a;
	int b;
};
class B:public A
{
public:
	B(int a,int b1,int b2):A(a,b1),b(b2) {}
	void print()
	{
		cout << a << "\t" << b << endl;
	}
protected:
	int b;
};

int main()
{
	B b(1, 2,3);
	b.print();//测试:1.会调用哪个print()2.会用哪个b?
	B* wbm = new B(1, 2, 3);//正常指针调用
	wbm->print();//测试2
	A* gzj = new B(1, 2, 3);
	gzj->print();//测试3

	return 0;
}

 有virtual

#include<iostream>

using namespace std;

class A
{
public:
	A(int a,int b):a(a),b(b) {}
	void print()
	{
		cout << a << endl;
	}
protected:
	int a;
	int b;
};
class B:virtual public A
{
public:
	B(int a,int b1,int b2):A(a,b1),b(b2) {}
	void print()
	{
		cout << a << "\t" << b << endl;
	}
protected:
	int b;
};

int main()
{
	B b(1, 2,3);
	b.print();//测试:1.会调用哪个print()2.会用哪个b?
	B* wbm = new B(1, 2, 3);//正常指针调用
	wbm->print();//测试2
	A* gzj = new B(1, 2, 3);
	gzj->print();//测试3:非正常赋值调用,看赋值类型即B 此处调用的是B的print()
	return 0;
}

3.虚继承-----"菱形继承"

以上这种情况,会出现两个a所以D该用哪个a?

1.用virtual继承由A继承到B和C ,此后a仅由祖父类决定,与BC类无关(尽管加类名限定也无效)(a始终保持一份!)。

2.   D写初始化参数成员列表必须调用祖父类的构造函数 

#include<iostream>

using namespace std;

class A
{
public:
	A(int a):a(a) {}
	void print()
	{
		cout << a << endl;
	}
	int a;
};
class B:virtual public A
{
public:
	B(int a,int b):A(a),b(b) {}
	int b;
};
class C :virtual public A
{
public:
	C(int a, int c) :A(a), c(c) {}
protected:
	int c;
};
class D :public B, public C
{
public:
	D():B(2,3),C(4,5),A(666){}
	void print()
	{
		cout << a << endl;
		cout << B::a << endl;
		cout << C::a << endl;
	}
protected:
};

int main()
{
	D d;
	d.print();
	return 0;
}

“只有一份a” 

四、构造和析构顺序问题 

1.单继承构造:先构造父类的(无论写不写初始化参数列表),再构造子类的=>析构顺序相反

#include<iostream>

using namespace std;

class A
{
public:
	A(int a) :a(a) { cout << "A"; }
	~A()
	{
		cout << "A";
	}
protected:
	int a;
};
class B:public A
{
public:
	B(int a, int b) :A(a), b(b) { cout << "B"; }
	~B()
	{
		cout << "B";
	}
protected:
	int b;
};

int main()
{
	B  b(1,2);
	return 0;
}

 //ABBA

2.多继承构造:①任何构造顺序问题,都和初始化参数列表无关

                        ②构造顺序和开头所写的继承顺序一致。

#include<iostream>

using namespace std;

class A
{
public:
	A(int a) :a(a) { cout << "A"; }
	~A()
	{
		cout << "A";
	}
protected:
	int a;
};
class B 
{
public:
	B(int b) : b(b) { cout << "B"; }
	~B()
	{
		cout << "B";
	}
protected:
	int b;
};
class C
{
public:
	C(int c) : c(c) { cout << "C"; }
	~C()
	{
		cout << "C";
	}
protected:
	int c;
};

class D :public B, public A, public C
{
public:
	D(int d = 0) :A(2), B(1), C(321), d(d) { cout << "D"; }
	~D()
	{
		cout << "D";
	}
protected:
	int d;
};

int main()
{
	D d;
	return 0;
}

与参数列表的顺序无关!

练习:

1. 设计一个类父类 Shape类 设计多个子类:Rect类 Circle类 分别求出并打印相应形状的周长和面积

2.设计类老师类,设计一个学生类,多继承产生一个研究生类,打印相关研究生的信息

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

打赏作者

_Ocean__

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

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

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

打赏作者

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

抵扣说明:

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

余额充值