c++继承知识详解(一)

2023-10-10 14:05:49 浏览数 (1)

继承好处: 减少重复的代码 语法: class 子类(派生类):继承方式 父类(基类) 继承方式: 公共继承,保护继承,私有继承

代码语言:javascript复制
#include<iostream>
using namespace std;
/*
class baise  
{
public:
	int ma;
protected:
	int mb;
private:
	int mc;
};
//定义一个父类,里面有3种
//儿子以公共方式继承父类
class son :public baise
{
//注意:
	//父类中所有非静态成员属性会被子类继承下去
	//父类中私有成员属性是被编译器·隐藏起来了,但是确实是被继承下来了
	int mb;
	void fun()
	{
		ma = 100; // 父类公共内容  以公共继承方式,类内 类外可以访问,也是公共权限
		mb = 100; // 父类保护内容  以公共继承方式,类内可以访问,类外不能访问,也是保护权限
		//mc = 100;父类的私有内容,以公共继承方式,访问不到
	}
};
void test01()
{
	son s1;
	s1.ma = 100;
	//s1.mb = 100; 保护权限,类外不能访问

	cout << sizeof(s1) << endl;
}

//以保护权限来继承父类

代码语言:javascript复制
class son2 :protected baise
{
	void func()
	{
		ma = 100;//父类公共内容  以保护继承方式,类内可以访问,类外不能,是保护权限
		mb = 100; //父类保护内容  以保护继承方式,类内可以访问,类外不能,是保护权限
		//mc = 100;父类的私有内容,以保护继承方式,访问不到
	}
};
void test02()
{
	son2 s2;
	//以保护权限继承,类外都不能访问
	/*s2.ma = 100;
	* s2.mb=100;
	*/
/*
}

//以私有权限继承父类
class son3 :private baise
{
	void func()
	{
		ma = 100;//父类公共内容  以私有继承方式,类内可以访问,类外不能,是私有权限
		mb = 100; //父类保护内容  以私有继承方式,类内可以访问,类外不能,是私有权限
		//mc = 100;父类的私有内容,以保护继承方式,访问不到
	}
};
void test03()
{
	son3 s3;
	//s2.ma = 100;
	//s2.mb=100;

}
*/

//继承中同名成员处理

代码语言:javascript复制
class base
{
public:
	base()
	{
		ma = 100;
	}
	int ma;
};
class sonn :public base
{
public:
	sonn()
	{
		ma = 10;
	}
	int ma;
};
//同名成员
void testt()
{
	sonn s;
	cout << "子类中的成员.访问" << s.ma << endl;
	cout << "父类中的成员base::作用域访问" << s.base::ma << endl;
}

//同名函数

  • 如果子类中没有,只有父类中有,直接调用会调用父类中的函数
  • 直接调用,调用的·是子类中同名的成员
  • 如果子类中出现与父类同名的成员函数,会隐藏掉父类中所有同名的函数,除非加上作用域
  • 总结:
  • 子类对象可以直接访问到子类中的同名成员
  • 子类对象加作用域可以访问到父类中同名的成员
  • 当子类和父类有同名的成员函数时,子类会隐藏父类中同名成员函数,,加作用域可以访问到父类中同名的函数

//同名静态成员处理 //同名静态成员属性

代码语言:javascript复制
class person
{
public:
	static int ma;
	static void func()
	{
		cout << "person的成员函数的调用" << endl;
	}
	static void func(int a)
	{
		cout << "person(int a)的成员函数的调用" << endl;
	}
};
int person::ma = 100;
class personson :public person
{
public:
	static int ma;
	static void func()
	{
		cout << "personson的成员函数的调用" << endl;
	}
};

int personson::ma = 200;

void test01()
{
	//1.通过对象访问
	cout << "1.通过对象访问" << endl;
	personson p; //实例化
	cout <<"personson下:"<< p.ma << endl;
    cout << "person下"<<p.person::ma << endl;
	
	//2.通过类名访问
	cout << "2.通过类名访问" << endl;
	//第一个::代表通过类名方式访问
	//第二个::代表访问父类作用域下
	cout<<"person下"<< personson::person::ma << endl;
	cout<<"personson下" << personson::ma << endl;
}

//同名静态成员函数

代码语言:javascript复制
void test02()
{
	//通过对象访问
	personson p;
	p.func();
	p.person::func();

	//通过类名方式访问
	personson::person::func();
	personson::func();
	//错误personson::func(10); 在personson下没有类似void func(int a)的函数
	personson::person::func(10);
}

//多继承语法 语法:class 子类:继承方式 父类1,继承方式 父类2,…

  • 多继承中如果父类中出现了同名的情况,子类中使用的时候要加作用域来区分
代码语言:javascript复制
class base1
{
public:
	base1()
	{
		ma = 100;

	}
	int ma;
};
class base2
{
public:
	base2()
	{
		mb = 200;
		ma = 200;
	}
	int mb;
	int ma;
};

//现在要有一个子类,来继承base1 base2

代码语言:javascript复制
class base3 :public base1, public base2
{
public:
	base3()
	{
		mc = 300;
		md = 400;
	}
	int mc;
	int md;
};
void test03()
{
	base3 b;
	cout << sizeof(b) << endl;
	//错误-》因为名字重复要用作用域加以区分cout << b.ma << endl;
	cout << "base1下" << b.base1::ma << endl;
	cout << "base2下" << b.base2::ma << endl;
}

//利用虚继承可以解决 菱形继承问题 //主要带来问题是子类继承两份相同的数据,导致资源浪费以及毫无意义

代码语言:javascript复制
class animal
{
public:
	int age;
};
//加入virtual后变成虚继承,animal叫虚基类
//从而统一
class monkey:virtual public animal{};
class xingxing:virtual public animal{};
//不管猴子还是猩猩,都是动物,所以虚继承animal类
class persons:public monkey,public xingxing{};
/*
* 对象模型:
* class persons   size(8):
         ---
 0      |  --- (base class monkey)
 0      | |  --- (base class animal)
 0      | | | age
        | |  ---
        |  ---
 4      |  --- (base class xingxing)
 4      | |  --- (base class animal)
 4      | | | age
        | |  ---
        |  ---
         ---
*/


//虚继承之后对象模型:
/*
* class persons   size(12):
         ---
 0      |  --- (base class monkey)
 0      | | {vbptr}
        |  ---
 4      |  --- (base class xingxing)
 4      | | {vbptr}
        |  ---
         ---
         --- (virtual base animal)
 8      | age
         ---

persons::$vbtable@monkey@:
 0      | 0
 1      | 8 (personsd(monkey 0)animal)

persons::$vbtable@xingxing@:
 0      | 0
 1      | 4 (personsd(xingxing 0)animal)
vbi:       class  offset o.vbptr  o.vbte fVtorDisp
          animal       8       0       4 0
*/

/*

  • 解释:
  • vbptr 虚基类指针
  • v代表 virtual
  • b 代表 base
  • ptr 代表 pointer
  • 8 | age
  • 0 | ±-- (base class monkey) 0 | | {vbptr} persons::$vbtable@monkey@: 0 | 0 1 | 8 (personsd(monkey 0)animal)

偏移量是8 0 8=8

4 | ±-- (base class xingxing) 4 | | {vbptr} persons::$vbtable@xingxing@: 0 | 0 1 | 4 (personsd(xingxing 0)animal)

偏移量是4 4 4=8 所以会找到同一个数据,只有一份 */

代码语言:javascript复制
void test04()
{
	persons p;
	p.monkey::age = 100;//monkey::作用域下
	p.xingxing::age = 200;//xingxing::作用域下
	cout << p.monkey::age << endl;
	cout << p.xingxing::age << endl;
	cout << p.age << endl;
}
代码语言:javascript复制
int main()
{
	//testt();
	//test01();
	//test02();
	//test03();
	test04();
	system("pause");
	return 0;
}

当父类中有保护权限,私有权限时,会继承到子类中吗? 按道理来说,父类中所有非静态成员属性会被子类继承下去,所以父类中私有成员属性确实是被继承下来了,但是被编译器隐藏起来了。

可以利用开发命令提示工具查看对象·模型 (更清晰,明了) 首先先跳转到该位置的盘 比如 D:盘等 cd 到指定具体位置下的文件路径(看自己写的文件名) 输入 cl /d1 reportSingleClassLayout类名 文件名

最后说明一下: 继承中构造和析构的顺序是?: 先构造父类,再构造子类 先析构子类,再析构父类

0 人点赞