33 继承

类与类之间的关系 继承

1 继承说明

1 子类拥有父类的所有变量和成员函数

2 子类可以拥有父类没有的方法和属性

#include<iostream>
using namespace std;

class Parent {
public:
	void print() {
		cout << "a:" << a << endl;
		cout << "b:" << b << endl;
	}
	int a;
	int b;
};

//class Children :private Parent
//class Children :protected Parent

class Children :public Parent {
private:
	int c;
};

void main() {
	Children c1;
	c1.a = 2;
	c1.b = 3;
	c1.print();
}

2 子类的访问控制

1 单个类的访问控制

C++继承方式对子类访问影响
  1. public继承, 父类成员在子类中保持原有访问级别
  2. private继承, 父类成员在子类中变为private成员
  3. protected继承, 父类public成员在子类变为protected;父类protected成员在子类仍为protected;父类private成员在子类仍为private; protected 关键字修饰的成员变量和成员函数是为了继承

private成员在子类中依然存在,但是无法访问,不论哪种继承,子类都无法使用父类的私有成员
在这里插入图片描述

共有继承

// public 修饰成员变量和方法 类内部和外部都能使用
// private 修饰成员变量和方法 类内部使用,继承子类中可用
// private 修饰成员变量和方法 类内部使用 外部不能用
class Parent {
public:
	int a;
protected:
	int b;
private:
	int c;

public:
	void printT() {
		cout << "printT" << endl;
	}
};

class Children :public Parent {
public:
	void useVar() {
		a = 0;
		b = 0;
		//c = 0; 不能访问
	}
};

void main() {
	Parent t1, t2, t3;
	t1.a = 10;
	// t1.b = 20; // 不能访问
	// t1.c = 30; // 不能访问
}

私有继承

class Parent {
public:
	int a;
protected:
	int b;
private:
	int c;

public:
	void printT() {
		cout << "printT" << endl;
	}
};

class Children2 :private Parent {
public:
	void useVar() {
		a = 0;
		b = 0;
		// c = 0; 不能访问
	}
};

void main() {
	Children2 c2;
	/*c2.a = 10;		不能访问	
	c2.b = 20;
	c2.c = 30;*/
}

保护继承

class Parent {
public:
	int a;
protected:
	int b;
private:
	int c;

public:
	void printT() {
		cout << "printT" << endl;
	}
};

class Children3 :protected Parent {
public:
	void useVar() {
		a = 0;
		b = 0;
		// c = 0; //不能访问
	}
};

void main() {
	Children3 c3;
	/*c3.a = 10;		
	c3.b = 20;
	c3.c = 30;*/
}

判断时看调用语句在类的内部还是类的外部;再看子类是怎么从父类继承的;再看父类的访问级别。

类的访问属性控制

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;
		cout << "b=" << b;
		cout << "c=" << c << endl;
	}
};

class C :protected A {
public:
	void print() {
		//cout << "a=" << a;
		cout << "b=" << b;
		cout << "c=" << c << endl;
	}
};

class D :private A {
public:
	void print() {
		//cout << "a=" << a;
		cout << "b=" << b;
		cout << "c=" << c << endl;
	}
};

void 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(10, 20, 30);
	// cc.set(40, 50, 60); // 保护
	// dd.set(70, 80, 90); // 

	bb.print();
	cc.print();
	// dd.print();
}

3 继承中的构造和析构

1 类型兼容性原则
  1. 子类对象当作父类对象使用
  2. 子类对象可以直接赋值给父类对象
  3. 子类对象可以初始化父类对象
  4. 父类指针可以直接指向子类对象
  5. 父类引用可以直接引用子类对象
#include<iostream>
using namespace std;


class Parent {
public:
	Parent() {
		cout << "构造函数" << endl;
	}
	Parent(const Parent& obj) {
		cout << "拷贝构造函数" << endl;
	}

	void printP() {
		cout << "parent" << endl;
	}
private:
	int a;
};

class Child :public Parent {
public:
	void printC() {
		cout << "child" << endl;
	}
private:
	int c;
};


void howToPrint(Parent* base) {
	base->printP();		// 父类成员函数
}

void howToPrint2(Parent &base) {
	base.printP();		// 父类成员函数
}

void main() {
	Parent p1;
	p1.printP();

	Child c1;
	c1.printC();
	c1.printP();

	// 类型兼容性原则
	// 1-1 基类指针(引用)指向子类对象
	Parent* p = NULL;
	p = &c1;
	p->printP();

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

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

	// 2
	// 让子类对象初始化父类对象
	// 子类就是一种特殊的父类
	Parent p3 = c1;
}
2 继承中对象模型
  1. 子类对象构造时,需要调用父类构造函数对其继承得来的成员进行初始化
  2. 子类对象析构时,需要调用父类析构函数对其继承得来的成员进行清理
3 先父类构造再子类构造,先子类析构再父类析构
// 先调用父类构造函数,再调用子类构造函数
// 析构顺序与构造相反
class Parent {
public:
	Parent(int a, int b) {
		this->a = a;
		this->b = b;
		cout << "parent构造函数" << endl;
	}
	/*Parent(const Parent& obj) {
		cout << "拷贝构造函数" << endl;
	}*/
	~Parent() {
		cout << "Parent析构函数" << endl;
	}
	void printP() {
		cout << "parent" << endl;
	}
private:
	int a;
	int b;
};

class Child :public Parent {
public:
	Child(int a, int b, int c):Parent(a,b) {
		this->c = c; 
		cout << "child构造函数" << endl;
	}
	~Child() {
		cout << "Child析构" << endl;
	}
	void printC() {
		cout << "child" << endl;
	}
private:
	int c;
};


void howToPrint(Parent* base) {
	base->printP();		// 父类成员函数
}

void howToPrint2(Parent &base) {
	base.printP();		// 父类成员函数
}

void objplay() {
	Child c1(1, 2, 3);
}

void main() {
	//Parent p(1, 2);
	objplay();
}

结果

parent构造函数
child构造函数
Child析构
Parent析构函数

4 继承和组合混搭

// 继承和组合混搭?
class Object {
public:
	Object(int a, int b) {
		this->a = a;
		this->b = b;
		cout << "Object构造函数" << " a " << a << " b " << b << endl;
	}
	~Object() {
		cout << "Object析构函数" << " a " << a << " b " << b << endl;
	}
protected:
	int a;
	int b;
};
class Parent:public Object {
public:
	Parent(char *p) :Object(1,2){
		this->p = p;
		cout << "Parent构造函数" << p << endl;
	}
	~Parent() {
		cout << "Parent析构函数" << p << endl;
	}
	void printP() {
		cout << "parent" << endl;
	}
protected:
	char* p;

};

class Child :public Parent {
public:
	Child(char *p) :Parent(p),obj1(3,4),obj2(5,6) {
		this->myp = p;
		cout << "child构造函数" << myp << endl;
	}
	~Child() {
		cout << "Child析构" << myp << endl;
	}
	void printC() {
		cout << "child" << endl;
	}
private:
	char* myp;
	Object obj1;
	Object obj2;
};


void objplay() {
	Child c1((char*)"继承测试");
}
void main() {
	objplay();
}

结果

Object构造函数 a 1 b 2
Parent构造函数继承测试
Object构造函数 a 3 b 4
Object构造函数 a 5 b 6
child构造函数继承测试
Child析构继承测试
Object析构函数 a 5 b 6
Object析构函数 a 3 b 4
Parent析构函数继承测试
Object析构函数 a 1 b 2

5 继承中的同名成员变量处理方法

class A {
public:
	int a;
	int b;
public:
	void get() {
		cout << "b: " << b << endl;
	}
	void print() {
		cout << "A" << endl;
	}
};

class B:public A {
public:
	int b;
	int c;
public:
	void get_child() {
		cout << "b: " << b << endl;
	}

	void print() {
		cout << "B" << endl;
	}
};

// 同名成员变量,同名成员函数
void main() {
	B b1;
	b1.b = 1;
	b1.get_child();

	b1.A::b = 100;	// 修改父类
	b1.B::b = 200;	// 修改子类 默认情况

	b1.get();

	b1.print();
	b1.A::print();
	b1.B::print();	// 默认情况
}  

结果

b: 1
b: 100
B
A
B

6 static

// 继承中static
class A {
public:
	static int a;
	int b;
	A() {
		cout << "A构造函数" << endl;
	}
public:
	void get() {
		cout << "b: " << b << endl;
	}
	void print() {
		cout << "A" << endl;
	}
};

int A::a = 100;	// 不仅变量赋值,更重要告诉编译器分配内存,继承类中使用a,不然报错

class B :private A {
public:
	int b;
	int c;
public:
	void get_child() {
		cout << "b: " << b << endl;
		cout << "a: " << a << endl;
	}

	void print() {
		cout << "B" << endl;
	}
};

// 1 static遵守派生类访问控制规则
// 2 int A::a = 100;不仅变量赋值,更重要告诉编译器分配内存,继承类中使用a,不然报错
// 3 A类中添加构造函数
void main() {
	A a1;
	a1.print();
	B b1;
	b1.get_child();
	// b1.a = 200;
}

多继承

1 一个类有多个直接基类继承关系(B继承Base1,Base2)

// 多继承
class Base1 {
public:
	Base1(int b1) {
		this->b1 = b1;
	}
	void printB1() {
		cout << "b1:" << b1 << endl;
	}
private:
	int b1;
};

class Base2 {
public:
	Base2(int b2) {
		this->b2 = b2;
	}
	void printB2() {
		cout << "b2:" << b2 << endl;
	}
private:
	int b2;
};

class B :public Base1, public Base2 {
public:
	B(int b1, int b2, int c) :Base1(b1),Base2(b2){
		this->c = c;
	}
	void printC() {
		cout << "c:" << c << endl;
	}
private:
	int c;
};

void main() {
	B b(1, 2, 3);
	b.printB1();
	b.printB2();
	b.printC();
}

2 虚继承

class B
class B1
class B2
C
// 虚继承
class B {
public:
	int b;
};

class B1:virtual public B {
public:
	int b1;
};

class B2:virtual public B{
public:
	int b2;
};

class C:public B1, public B2 {
public:
	int c;
};

void main() {
	C c1;
	c1.b1 = 100;
	c1.b2 = 200;
	c1.c = 300;

	c1.b = 500;	// b不明确,加virtual可以解决
}

不调用B中的b时,去掉virtual,调用两次B的构造函数

class B {
public:
	int b;
	B() {
		cout << "B构造函数" << endl;
	}
};
class B1 : public B {
public:
	int b1;
};

class B2 : public B {
public:
	int b2;
};

class C:public B1, public B2 {
public:
	int c;
};

void main() {
	C c1;
}

一个类有两个父类,且父类成员中有相同的名字

D1
E
D2
class D1 {
public:
	int k;
};

class D2 {
public:
	int k;
};

class E :public D1, public D2 {

};

void main() {
	E e1;
	e1.D1::k = 10;
	e1.D2::k = 20;
}

virtual关键字会给类变量增加属性

class B {
public:
	int b;
	B() {
		cout << "B构造函数" << endl;
	}
};
class B1:virtual public B {
public:
	int b1;
};
class B2 : public B {
public:
	int b2;
};

class C:public B1, public B2 {
public:
	int c;
};

void main() {
	cout << sizeof(B) << endl;	//4
	cout << sizeof(B1) << endl;	//12 virtual关键字会给变量增加属性
	cout << sizeof(B2) << endl;	//8
}
  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值