继承与派生

继承与派生

类的继承与派生

继承的优点和缺点:

  • 代码共享,减少创建类的工作量,每一个子类都有父类的方法和属性
  • 提高代码的重用性,减少代码的冗杂程度
  • 提高代码的可拓展性,调用别人的接口,加继承父类实现
  • 继承是侵入性的,子类拥有父类的全部属性和方法
  • 增强了耦合性,父类常量、变量、方法被修改时,子类可能需要重构

继承代码示例

class Student
{
public:
	Student(int id, string name)
	{
		this->id = id;
		this->name = name;
	}
	void printS()
	{
		cout << "id=" << this->id << " name=" << this->name << endl;
	}
private:
	int id;
	string name;
};

class Student2
{
public:
	Student2(int id, string name, int score)
	{
		this->id = id;
		this->name = name;
		this->score = score;
	}

	void printS()
	{
		cout << "id = " 
			<< this->id 
			<< ",name=" 
			<< this->name 
			<< endl;
		cout << "score= " << this->score << endl;
	}
private:
	int id;
	string name;
	int score;
};

//Student3继承于Student,子类继承了父类的成员和公有的函数
class Student3 :public Student
{
public:
	Student3(int id, string name, int score) :Student(id, name)
	{
		this->score = score;
	}

	void printS()
	{
		Student::printS();
		cout << "score = " << this->score << endl;
	}
private:
	int score;
};
//类Student3通过继承Student实现了类Student2的功能

派生类的组成,基类+新增成员

继承的方式

  • 只要是父类中的private成员,不管什么继承方式,子类都无法继承,但可以通过public来间接访问,比如get(),构造函数什么的
  • 如果是public继承,子类的访问控制权限保持不变
  • 如果是proteceed继承,子类中除了private成员,其余在子类中都是protected
  • 子类可以直接访问父类的public成员
  • 子类内部可以访问父类protected成员,但类外不能访问

三条原则:

  1. 看调用的成员变量是在类的外部还是在类的内部
  2. 看当前变量在子类中的访问控制权限
  3. 看子类的继承方式
publicprotectedprivate
公有继承(public)publicprotected不可见
保护继承(protected)protectedprotected不可见
私有继承(private)privateprivate不可见

代码示例:

class Parent
{
public:
	int pub;//类的内部和外部都可以访问
protected:
	int pro;//类的内部可以访问,类的外部不可以访问
private:
	int pri;//类的内部可以访问,类的外部不可以访问
};

class Child :public Parent
{
public:
	void func()
	{
		cout << pub << endl;
	}
};

//保护继承
class Child2 :protected Parent
{
public:
	void func2()
	{
		pub;//通过protected继承,能够在类的内部访问
			//pub在类的内部可以访问,类的外部不可以访问,子类可以访问
			//pub就是protected成员
		pro;//pro跟pub是一样的性质,都是protected
	}
};


class Sub_child2 :public Child2
{
public:
	void sub_func2()
	{
		pub;
		pro;
	}
};


//继承Child类
class SuChild :public Child
{
	void func2()
	{
	
	}
};

class Child3 :private Parent
{
public:
	void func3
	{
		pub;//类的内部可以访问,类的外部不能访问
			//子类不能访问
	    pro;//跟pub一样
	}
};

class Sub_Child3 :public Child3
{
public:
	void sun_fun3()
	{
		
	}
};

继承关系具体代码举例

#include<iostream>

using namespace std;

class A
{
private:
	int a;
protected:
	int b;
public:
	int c;
	A()
	{
		a = 0;
		b = 0;
		c = 0;
	}
	void set(int a, int b, int c)
	{
		this->a = a;
		this->b = b;
		this->c = c;
	}
};

class B :public A
{
public:
	void print()
	{
		//cout << "a= " << a;//a是父类的私有成员,访问不了
		cout << "b= " << b;//b在类的内部可以访问
		cout << "c= " << c << endl;//类的内部和外部都可以访问
	}
};


class C :protected A
{
public:
	void print()
	{
		//cout << "a= " << a;//a是父类的私有成员,访问不了
		cout << "b= " << b;//b在类的内部可以访问,类的外部不能访问
		cout << "c= " << c << endl;//类的内部和外部都可以访问
	}
};

class D :private A
{
public:
	void print()
	{
		//cout << "a= " << a;//a是父类的私有成员,访问不了
		cout << "b= " << b;//私有继承b在类的内部可以访问,外部不可以访问
		cout << "c= " << c << endl;//类的内部可以访问,外部不可以访问
	}
};


int main()
{
	A aa;
	B bb;
	C cc;
	D dd;
	aa.c = 100;
	bb.c = 100;
	//cc.c = 100;//不可访问
	//dd.c = 100;//不可访问
	aa.set(1, 2, 3);
	bb.set(1, 2, 3);
	//cc.set(1, 2, 3);//不能访问
	//dd.set(1, 2, 3);//不能访问
	bb.print();
	cc.print();
	dd.print();

	return 0;
}

类的兼容性原则

  1. 子类对象可以当做父类对象使用
  2. 子类对象可以直接赋值给父类对象
  3. 子类对象可以直接初始化父类对象
  4. 父类指针可以直接指向子类对象
  5. 父类引用可以直接引用子类对象

练习代码:

#include<iostream>
using namespace std;
class Parent
{
public:
	int a;
	//int c;
	void printP()
	{
		cout << "a" << this->a << endl;
	}
};

class Child :public Parent
{
public:
	void printC()
	{
		cout << "b=" << this->a;
	}
	int b;
};

void myPrint(Parent* pp)
{
	pp->printP;
}


int main(void)
{
	Parent* pp=NULL;
	Child* cp=NULL;

	Parent p;
	Child c;
	pp = &c;//c的内存布局能够满足父类指针的全部需求
			//可以用一个子类的对象地址给父类指针赋值
	pp->a;
	pp->printP(&c);
	return 0;	
}

子类的构造与析构

  • 子类构造函数会默认调用父类无参构造
  • 在子类构造函数之前会先调用父类的构造函数
  • 如果子类要调用父类的有参构造,需要给父类有参构造函数传值
  • 析构函数会先调用子类的析构函数然后才调用父类的析构函数

代码示例

#include<iostream>

using namespace std;

class Parent
{
public:
	Parent()
	{
		a = 0;
		cout << "parent()" << endl;
	}
	Parent(int a)
	{
		this->a = a;
		cout << "parent(int)" << endl;
	}

	~Parent()
	{
		cout << "Parent析构" << endl;
	}

	int a;
};

class Child :public Parent
{
public:
	//在调用子类,默认调用父类构造函数
	Child(int a,int b):Parent(a)
	{
		cout << "Child(int,int)..." << endl;
		this->a = a;
		this->b = b;
	}

	void printC()
	{
		cout << "b=" << b << endl;
	}
	~Child()
	{
		cout << "Child析构" << endl;
	}
	int b;
};

int main()
{
	Child c(10,20);
	c.printC();
	//c.~Child();
	return 0;
}

子类与父类的成员重名

  • 父类和子类即使成员变量名相同,但由于内存地址不同,不影响
  • 父类成员变量名通过::访问
  • 传参过程是先在子类构造函数建临时变量,通过临时变量传参

代码示例:

#include<iostream>

using namespace std;

class Parent
{
public:
	int a;
	Parent(int a)
	{
		this->a = a;
	}
};

class Child :public Parent
{
public:
	int a;
	Child(int p_a,int c_a):Parent(c_a)//Parent(p_a)
	{
		this->a = p_a;//this->a = c_a;
	}

	void print()
	{
		cout << Parent::a << endl;
		cout << this->a << endl;//子类的A
	}
};

int main()
{
	Child c(10, 100);
	c.print();
	return 0;
}

继承中的static

  • static在类内声明,在类外初始化
  • static归类,所有成员共享
  • static在继承关系中,同样也别被子类共享

多继承与虚继承

  • 关键字virtual,虚继承,在发生多继承的时候,子类重复的只会有一个继承

  • 多继承即一个子类继承了多个父类,仅C++有

    class 子类:public 父类,public 父类....
    
  • 虚继承重复的部分只有一块内存

代码示例:

#include<iostream>

using namespace std;

//定义家具类
class Furniture
{
public:
	int m;//材质
};


//继承父类虚继承,防止子类发生不明确现象
class Bed:virtual public Furniture
{
public:
	void sleep()
	{
		cout << "go to bed" << endl;
	}
};

class Sofa:virtual public Furniture
{
public:
	void sit()
	{
		cout << "relax on the sofa" << endl;
	}
};

class SofaBed:public Bed,public Sofa
{
public:
	void SleeAndSit()
	{
		sleep();
		sit();
	}
};

int main()
{
	Bed b;
	b.sleep();
	Sofa s;
	s.sit();
	cout << "-------------" << endl;
	SofaBed sb;
	sb.SleeAndSit();
	sb.m = 100;//如果不加vitural不明确只能够通过::访问 
	system("pause");
	return 0;
}
  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

打赏作者

Mr_Csyn

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

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

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

打赏作者

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

抵扣说明:

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

余额充值