类和对象-继承-C++

1.定义

面向对象的三大特征之一,为了减少重复的代码

2.语法

class 子类 :继承方式 父类   (子类也叫派生类,父类也称为基类)

例:class age:public person;

#include<iostream>
using namespace std;
#include<string>
class age;
class base
{
public:
	void header()
	{
		cout << "首页" << endl;
	}
	void footer()
	{
		cout << "尾页" << endl;
	}
};
class cpp :public base
{
public:
	void content()
	{
		cout << "视频内容" << endl;
	}
};
int main()
{
	cpp p;
	p.header();
	p.content();
	p.footer();
	system("pause");
	return 0;
}

3.继承方式

1.分类

公共继承 :原样复制父类中的类型,不可访问private

保护继承:将public变为protected类型,不可访问private

私有继承:将public和privated变为private,不可访问private

2.语法

(需要用函数来访问,并且函数也要有类型)

#include<iostream>
using namespace std;
#include<string>
class age;
class base
{
public:
	int a = 10;
protected:
	int b = 10;
private:
	int c = 10;
};
class cpp :public base
{
public:
	void fun()
	{
		a = 100;
		b = 100;
	}
};
int main()
{
	cpp p;
	system("pause");
	return 0;
}

注意:子类中不能访问父类中的private类型

错误示例

#include<iostream>
using namespace std;
#include<string>
class age;
class base
{
public:
	int a = 10;
protected:
	int b = 10;
private:
	int c = 10;
};
class cpp :public base
{
public:
	void fun()
	{
		a = 100;
		b = 100;
		c = 100;
	}
};
int main()
{
	cpp p;
	system("pause");
	return 0;
}

4.继承中的对象模型

结论:父类中所有非静态成员都会被继承下去,私有成员属性是被编译器隐藏了,隐刺是访问不到的,但确实是被继承下去了。

#include<iostream>
using namespace std;
#include<string>
class age;
class base
{
public:
	int a = 10;
protected:
	int b = 10;
private:
	int c = 10;
};
class cpp :public base
{
public:
	int d = 10;

};
int main()
{
	cpp p;
	cout << "size:" << sizeof(cpp) << endl;
	system("pause");
	return 0;
}

注意:可以利用开发人员命令提示符工具查看对象模型。

先进后出

5.构造和析构顺序

先构造父类再构造子类,析构的顺序与构造的顺序相反。

#include<iostream>
using namespace std;
#include<string>
class age;
class base
{
public:
	base()
	{
		cout << "base构造函数" << endl;
	}
	~base()
	{
		cout << "base析构函数" << endl;
	}
};
class cpp :public base
{
public:
	cpp()
	{
		cout << "cpp构造函数" << endl;
	}
	~cpp()
	{
		cout << "cpp析构函数" << endl;
	}

};
int main()
{
	cpp p;
	return 0;
}

6.同名成员处理

当父类中的属性和子类中的属性重合的情况

cout<<"子类下面的成员"<<s.m_a<<endl;
cout<<"父类下面的成员"<<s.base::m_a<<endl;

7.同名函数处理

1.直接调用调用的是子类中的同名成员

(如果子类中出现和父类同名的成员函数,子类中的同名函数会隐藏父类中的所有同名)

s.fun();

2.调用父类中的同名成员

(如果想访问父类中被隐藏的成员函数,需要加作用域)

s.base::fun();

8.同名静态成员访问

1.通过对象访问

cout<<"子类"<<s.m_a<<endl;
cout<<"父类"<<s.base::m_a<<endl;

2.通过类名访问

cout<<"子类"<<son::m_a<<endl;
cout<<"父类"<<base::m_a<<endl;
cout<<"父类"<<son::base::m_a<<endl;

9.同名静态函数访问

子类中如果出现和父类中同名的静态成员函数,会隐藏父类中的静态成员函数。

如果想访问父类中的静态成员函数,需要加作用域。

10.多继承语法

C++允许一个类继承多个类

语法:class 子类:继承方式 父类1,继承方式 父类2。。。

注意

1.不过多继承可能会引发父类中有同名成员出现,需要加作用域来区分,所以C++实际开发中不建议使用多继承。

2.当父类中出现同名成员,需要加作用域来区分

cout<<"1号父类"<<s.base1::m_a<<endl;
cout<<"2号父类"<<s.base2::m_a<<endl;

11.菱形继承问题

带来的影响是他会继承两份age,占用两份资源,造成浪费。

1.图示

2.代码演示

#include<iostream>
using namespace std;
#include<string>
class animal
{
public:
	int age = 15;
};
class sheep:public animal
{
public:
	int age = 10;
};
class camel:public animal
{
public:
	int age = 20;
};
class cnm :public sheep, public camel
{};
int main()
{
	animal a;
	sheep b;
	camel c;
	cnm d;
	cout << "animal:" << a.age << endl;
	cout << "sheep:" << b.age << endl;
	cout << "camel:" << c.age << endl;
	cout << "animal 2:" << a.age << endl;
	cout << "sheep 2:" << b.age << endl;
	cout << "camel 2:" << c.age << endl;
	cout << "cnm.sheep:" << d.sheep::age << endl;
	cout << "cnm.camel:" << d.camel::age << endl;
	return 0;
}

注意:当菱形继承时,两个父类拥有相同的数据,需要加以作用域区分。cnm只有一个age就可以,菱形继承导致有两个age,造成数据浪费。

错误示范:

#include<iostream>
using namespace std;
#include<string>
class animal
{
public:
	int age = 15;
};
class sheep:public animal
{
};
class camel:public animal
{
};
class cnm :public sheep, public camel
{};
int main()
{
	animal a;
	sheep b;
	camel c;
	cnm d;
	cout << "cnm:" << d.age << endl;//会报错
	return 0;
}

3.解决方法

利用虚继承解决菱形继承问题

1.语法

继承之前,加上关键字virtual变为虚继承。此时的animal称为虚基类。

2.代码演示
#include<iostream>
using namespace std;
#include<string>
class animal
{
public:
	int age = 15;
};
class sheep:virtual public animal
{
};
class camel:virtual public animal
{
};
class cnm :public sheep, public camel
{};
int main()
{
	animal a;
	sheep b;
	camel c;
	cnm d;
	d.sheep::age = 10;
	d.camel::age = 20;
	cout << "cnm.sheep:" << d.sheep::age << endl;
	cout << "cnm.camel:" << d.camel::age << endl;
	cout << "cnm:" << d.age << endl;
	return 0;
}

在菱形继承的中间两层加上关键字virtual之后,访问a.sheep::age和a.camel::age结果都变为最后更改的值,也可以用    cout << "cnm:" << d.age << endl;进行访问了。(相当于这四个继承够公用一个age)

3.底层原理

virtual关键字其实让继承的由一个变量变为了继承一个指针。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值