C++面向对象编程(六) 继承

本文详细介绍了 C++ 中的类继承概念,包括 has-A、use-A 和 is-A 关系,以及不同继承方式(public、protected 和 private)对访问权限的影响。同时,通过实例演示了如何定义和使用继承类及构造函数。

首先,类之间的关系有三种:

has-A (包含关系),即:一个类中的数据成员是另一种以经定义的类对象。

use-A   (组合关系)  , 即:一个类中部分地使用另一个类,通过类之间成员函数的相互联系,

定义友元成员函数或对象参数传递实现。

is-A      (继承关系)。关系具体传递性,但不具有对称性。


 类继承关系的语法形式:


class 派生类名 : 基类名表

{

数据成员和成员函数声明;

}

基类名表构成:

访问控制 基类名,访问控制 基类名,...访问控制 基类名

访问控制表示派生类对基类的继承方式,使用关键字:

public: 公有继承 (项目开发中经常用public 继承)

protected: 保护继承

private: 私有继承


继承的重要说明:

  1. 子类拥有父类的所有成员变量和函数
  2. 子类是一种特殊的父类
  3. 子类对象可以当作父类对象使用
  4. 子类可以拥有父类没有的方法和属性

子类继承了父类的全部成员变量和成员方法(除了构造函数,拷贝构造函数,

析构函数之外的成员方法),但是这些成员的访问属性,在派生过程中是可以调整的。


C++中的继承方式会影响子类的对外访问属性。

public继承:父类成员在子类中保持原有的访问级别。

private继承:父类成员在子类中变为private成员

protected继承:父类中public成员会变成protected

 父类中的protected成员仍然为protected

  父类中private成员仍然为private


private成员在在子类中依然存在,只是不能访问。不论是哪种继承方式,子类都不能直接使用父类的私有成员。


判断某一句话,是否可以被访问.

  1. 看调用语句,这句话,写在子类的内部,还是外部
  2. 看子类是如何从父类继承(public,protected,private)
  3. 看父类中的访问级别(public,private,protected)

protected 关键字,修饰的成员变量和成员函数,是为了在家族(子类的类里面)中使用。


类型兼容原则(赋值兼容原则)

类型兼容原则指:在需要父类对象的任何地方,都可以使用公有派生类的对象来替代。


类型兼容原则所指替代情况有:

  1. 子类对象可以当作父类对象使用
  2. 子类对象可以直接赋值给父类对象
  3. 子类对象可以直接初始化父类对象
  4. 父类指针可以直接指向子类对象
  5. 父类引用可以直接引用子类对象
在替代之后,子类对象就可以作为父类的对象使用,但是只可以使用从父类继承的成员

总结:子类就是特殊的父类。


#include <iostream>
using namespace std;

class Parent
{
public:
	void printP()
	{
		cout << " 我是父亲" << endl;
	}
private:
	int a;
};

class Child : public Parent
{
public:
	void printC()
	{
		cout << "我是儿子" << endl;
	}
private:
	int c;
};

/*
兼容规则中所指的替代包括以下情况:
子类对象可以当作父类对象使用
子类对象可以直接赋值给父类对象
子类对象可以直接初始化父类对象
父类指针可以直接指向子类对象
父类引用可以直接引用子类对象
*/

void howToPrint(Parent *base)
{
	base->printP();//只能执行时父类的成员
}

void howToPrint2(Parent &base)
{
	base.printP();//只能执行时父类的成员
}

int main()
{
	Parent p1;
	p1.printP();
	Child c1;
	c1.printC();
	c1.printP();
	//赋值兼容性原则
	//1. 父类指针(引用) 指向 子类对象
	Parent *p = NULL;
	p = &c1;
	p->printP();

    //2.指针做函数参数
	howToPrint(&p1);
	howToPrint(&c1);

	//3.引用做函数参数
	howToPrint2(p1);
	howToPrint2(c1);

	//子类对象可以直接初始化父类对象
	Parent p3 = c1;
	system("pause");
	return 0;
}


Student是一个已经定义的类


如果一个类中包含 另一个类的对象(Student  s1,)作为数据成员,

如 class Teacher

{

protected:

int a;

int b;

Student s1;  //此时,s1称为子对象,或者组合对象。

}



定义子类的构造函数的一般形式为:


子类构造函数名(总参数列表):父类构造函数名(参数列表) : 子对象名(参数列表)

{

派生类中新增数据成员初始化语句;

}


子类的构造函数的顺序是:

  1. 调用父类的构造函数,对父类的数据成员初始化;
  2. 调用子对象构造函数,对子对象数据成员初始化;
  3. 再执行子类的构造函数本身,对子类的数据成员初始化。

#include <iostream>
using namespace std;

class Object
{
public:
	Object(int a, int b)
	{
		this->a = a;
		this->b = b;
		cout << "object 构造函数执行" << "a "<< a << " b " << b << endl;
	}
	~Object()
	{
		cout << "object析构函数 \n";
	}
protected:
	int a;
	int b;
};
class Parent : public Object
{
public:
	Parent(char* p):Object(1,2)
	{
		this->p = p;
		cout << " 父亲构造函数" << p << endl;
	}
	~Parent()
	{
		cout << " 父类的析构函数" <<  p << endl;
	}
	void printP(int a, int b)
	{ 
		cout << "我是父亲" << endl;
	}
protected:
	char* p;
 
};

class Child : public Parent
{
public:

	Child(char *p):Parent(p),obj1(3,4),obj2(5,6)
	{
		this->myp = p;
		cout << "我是子类的构造函数" << myp << endl;
	}
	~Child()
	{
		cout << "子类的析构函数" <<  myp << endl;
	}
	void printC()
	{
		cout << "我是儿子" << endl;
	}
protected:
	char* myp;
	Object obj1;
	Object obj2;
};

void playObj()
{
	 Child c1("继承测试");

}


int main()
{
	playObj();

	system("pause");
	return 0;
}







评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值