c++继承知识总结

news/2024/7/7 7:15:50

 c++继承相关知识总结

继承关系:public protected private 
 
 不矫情 直接贴代码 举例
  代码主要从:
a. 基类成员对其对象的可见性:  只有public成员可以访问
b. 基类成员对派生类的可见性:  
c. 基类成员对派生类对象的可见性:
  父类(基类) 

class Base
{
public:
	Base()
	{
		_pri = 1;
		_pro = 2;
		_pub = 3;
	}
private:
	int _pri;
protected:
	int _pro;
public:
	int _pub;
};

 (1)public 继承方式
 
class Derived1 :public Base
{
public:
	Derived1()
	{
		_d1_pri = 4;
		_d1_pro = 5;
		_d1_pub = 6;
	}
	void showd()
	{
		_pub = 0;   // 仍为public成员
		_pro = 2;   //  仍为protected成员
		//_pri = 3; // 父类私有成员对子类 不可见
		
	}
private:
	int _d1_pri;
protected:
	int _d1_pro;
public:
	int _d1_pub;
};
void TestPublic()
{
	Base b;
	b._pub = 1;
	//b._pro = 2;  // 父类对象不可访问父类保护成员
	//b._pri = 3;  // 父类对象不可访问父类私有成员
	Derived1 d1;
	d1._pub = 1; // 子类对象可以访问父类公有成员
	//d1._pro = 2; //子类对象不可访问父类保护成员
	//d1._pri = 3; // 子类对象不可访问父类私有成员
	d1._d1_pub = 4;
}
(2) protected继承
  
// protected 保护继承
class Derived2 :protected Base
{
public:
	Derived2()
	{
		_d2_pri = 4;
		_d2_pro = 5;
		_d2_pub = 6;
	}
	void showd()
	{
		_pub = 1;   //  变为子类的protected成员
		_pro = 2;   //  仍为protected成员
		//_pri = 3; // 父类私有成员对子类不可见

	}
private:
	int _d2_pri;
protected:
	int _d2_pro;
public:
	int _d2_pub;
};
void TestProtected()
{
	Base b;
	b._pub = 1;
	//b._pro = 2;  // 父类对象不可访问父类保护成员
	//b._pri = 3;  // 父类对象不可访问父类私有成员
	Derived2 d2;
	//d2._pub = 1; // 父类的public成员权限被修改为protected,子类对象不可访问
	//d2._pro = 2; //子类对象不可访问父类保护成员
	//d2._pri = 3; // 子类对象不可访问父类私有成员
	d2._d2_pub = 4;
}
(3)私有继承
// private私有继承
class Derived3 :private Base
{
public:
	Derived3()
	{
		_d3_pri = 4;
		_d3_pro = 5;
		_d3_pub = 6;
	}
	void showd()
	{
		_pub = 1;   //  变为子类的privite成员
		_pro = 2;   //  变为子类的privite成员
		//_pri = 3; // 父类私有成员对子类不可见

	}
private:
	int _d3_pri;
protected:
	int _d3_pro;
public:
	int _d3_pub;
};
void TestPrivate()
{
	Base b;
	b._pub = 1;
	//b._pro = 2;  // 父类对象不可访问父类保护成员
	//b._pri = 3;  // 父类对象不可访问父类私有成员
	Derived3 d3;
	//d3._pub = 1; // 父类的public成员权限被修改为private,子类对象不可访问
	//d3._pro = 2; // 父类的protected成员权限被修改为private,子类对象不可访问
	//d3._pri = 3; // 子类对象不可访问父类私有成员
	d3._d3_pub = 4;
}
    总结一下继承方式 
    1 基类的private成员在派生类中是不能被访问的,如果基类成员不想在类外直接被访问,但需要在派生类中能访问,就定义为protected。可以看出保护成员限定符是因继承才出现的。
    2不管是哪种继承方式在派生类内部都可以访问基类的公有成员和保护成员,基类的私有成员存在但是在子类中不可见(不能访问)。
    3 使用关键字class时默认的继承方式是private,使用struct时默认的继承方式是public,不过最好显示的写出继承方式。
  派生类(子类)的默认成员函数
  
  1 继承关系中构造函数和析构函数
   (1)继承关系中的构造函数和析构函数的调用
           构造函数的调用顺序 :Derived d;
     
        析构函数的调用顺序 :
       
             
说明:
       a 、基类没有缺省构造函数,派生类必须要在初始化列表中显式给出基类名和参数列表。
       b、基类没有定义构造函数,则派生类也可以不用定义,全部使用缺省构造函数。
       c、基类定义了带有形参表构造函数,派生类就一定定义构造函数 (无参或者带参)

 代码举例
     
<span style="font-size:18px;">class A{
public:
    A(){cout<<"this is A::A()"<<endl;}
    A(int b){cout<<"this is A::A(int b):    the value of b is: "<<b<<endl;}
    A(double b){cout<<"this is A::A(double b)    the value of b is: "<<b<<endl;}
};
class B:public A{
public:
    B():A(){}  //调用基类 A 默认构造函数
    B(int b):A(b){} //调用基类 A 的 A::A(int b) 构造函数
    B(double b):A(b){} //调用基类 A 的 A::A(double b) 构造函数
};
void main()
{
    B b0,b1(5),b2(10.5);//产生三个实例,分别调用不同的基类构造函数
    system("pause");
}
/***********************************
调用 func 函数的输出结果:
this is A::A()
this is A::A(int b):    the value of b is: 5
this is A::A(double b)    the value of b is: 10.5
***********************************/</span>


   
  2继承体系中的作用域
   2.a. 在继承体系中基类和派生类是两个不同作用域。
   2.b. 子类和父类中有同名成员,子类成员将屏蔽父类对成员的直接访问。(在子类成员函数中,可以使用 基类::基   类 成员 访问)--隐藏 --重定义
   2.c. 注意在实际中在继承体系里面最好不要定义同名的成员。
 3继承与转换--赋值兼容规则--public继承  
记忆法: 大的可以赋值给小的
      注意:只有public继承才有
   3.a. 子类对象可以赋值给父类对象(切割/切片)
   3.b. 父类对象不能赋值给子类对象
   3.c. 父类的指针/引用可以指向子类对象
   3.d. 子类的指针/引用不能指向父类对象(可以通过强制类型转换完成) 
    
 4 友元与继承
  友元关系不能继承,也就是说基类友元不能访问子类私有和保护成员
 
  注意下面的例子:<<运算符的重载函数 不能说明友元关系可以继承

<span style="font-size:18px;">class Base
{
public:
	friend ostream& operator<<(ostream& _cout,Base &base)
	{
		_cout << base._pri << endl;
		return _cout;
	}
private:
	int _pri;
};

class Derived :public Base
{
};

void TestBase()
{
	Base b;
	cout << b; 
	Derived d;
	cout << d; // 参数发生类型转换 派生类对象赋值给基类对象
	
}</span>

三 继承方式 单继承 多继承( 菱形继承)
   单继承 
   
class A
{
public:
	A()
	{
		_a = 1;
	}
public:
	int _a;
};
class B: public A
{
public:
	B()
	{
		_b = 2;
	}
public:
	int _b;
};
// 创建一个B 类的对象b   查看内存 0x004FFAD8  00000001 00000002 

单继承的数据模型

 多继承(普通)
 
class A
{
public:
	A(int a)
		:_a(a)
	{
	}
public:
	int _a;
};
class B
{
public:
	B(int b)
		:_b(b)
	{
	}
public:
	int _b;<strong>
</strong>};
class C:public A,public B
{
public:
	C(int a,int b,int c)
		: B(a)   //  不是按初始化顺序来初始化派生类的
		, A(b)   //  而是按继承顺序 public A public B  来调用其构造函数
		, _c(c)
	{
	}
public:
	int _c;
};
//创建一个C 类的对象c   查看内存 0x0023F904  00000002 00000001 00000003
  数据模型:
   

   多继承中的菱形继承(也叫钻石继承)
 
class A
{
public:
	A(int a = 0)
	{
	}
public:
	int _a;
};
class B1:public A
{
public:
	B1(int b)
		:_b1(b)
	{
	}
public:
	int _b1;
};
class B2 :public A
{
public:
	B2(int b2)
		:_b2(b2)
	{
	}
public:
	int _b2;
};
class C :public B1,public B2
{
public:
	C(int b1,int b2,int c)
		: B1(b1)
		, B2(b2)
		, _c(c)
	{
	}
public:
	int _c;
};
void testD()
{
	C c(1,2,3);
	c.B1::_a = 4; // 必须指定_a的作用域 不然不知道_a属于B1 还是B2
	c.B2::_a = 5; // 因此这样就存在二义性 
}

数据模型
  
  
 由于存在二义性 因此引入虚继承

虚继承:
 
class A
{
public:
	A(int a = 0)
	{
		_a = a;
	}
public:
	int _a;
};
class B1:virtual public A
{
public:
	B1(int b)
		:_b1(b)
	{
	}
public:
	int _b1;
};
class B2 :virtual public A
{
public:
	B2(int b2)
		:_b2(b2)
	{
	}
public:
	int _b2;
};
class C :public B1,public B2
{
public:
	C(int b1,int b2,int c)
		: B1(b1)
		, B2(b2)
		, _c(c)
	{
	}
public:
	int _c;
};
void testD()
{
	cout << sizeof(C) << endl; // 24  B1的大小(8)+B2的大小(8)+C的成员变量(4) =20 多了4个字节
	C c(1,2,3);
	//c._a = 1; // 这样就不用作用域限定来指定_a所属
}
 数据模型:
  


关于 继承这块 就给大家分享这么多了,欢迎大家指错





http://www.niftyadmin.cn/n/4136285.html

相关文章

python字符串小数转化整数_Python字符串、整数、和浮点型数相互转换实例

前言序锦 在编程中&#xff0c;经常要用到字符串的相互转换&#xff0c;现在在这里记录一下Python里面的字符串和整数以及浮点型数之间是如何进行相互转换的。 int(str)函数将符合整数的规定的字符串转换成int型的 float(str)函数将符合浮点型的规定的字符串转换成float型的 st…

《编程之法》1.3字符串的全排列,组合,重复排列,八皇后问题

题目描述&#xff1a;输入一个字符串&#xff0c;打印出该字符串中字符的所有排列&#xff0c;例如输入"abc"&#xff0c;输出"abc","acb","bac","bca","cab","cba" 解法一&#xff1a;递归实现 类似于…

强强学Android_自定义Button

自定义开关 学习笔记如有错误之处请大家帮忙指出纠正__谢谢-------------------------------------------------------------------------------------------------------------------------------------------难点总结 : 一个自定义控件 即实现了触摸事件 又实现了点击事件 ,…

为什么构造函数不可以声明为虚函数,而析构函数可以

构造函数不能声明为虚函数&#xff0c;析构函数可以声明为虚函数&#xff0c;而且有时是必须声明为虚函数。 不建议在构造函数和析构函数里面调用虚函数。 构造函数不能声明为虚函数的原因是: 1 构造一个对象的时候&#xff0c;必须知道对象的实际类型&#xff0c;而虚函数行为…

什么情况下c++编译器会合成默认构造函数

问题&#xff1a;对c初学者来说存在一个误区&#xff0c;如果类没有定义任何构造函数&#xff0c;编译器会自动生成默认的构造函数。 注意&#xff1a;这种说法是错误的。 正确的说法&#xff1a;惟有默认构造函数”被需要“的时候编译器才会合成默认构造函数。 那什么情况…

halcon显示坐标_初识halcon(一)

halcon介绍HALCON是德国MVtec公司开发的一套完善的标准的机器视觉算法包&#xff0c;拥有应用广泛的机器视觉集成开发环境。它节约了产品成本&#xff0c;缩短了软件开发周期——HALCON灵活的架构便于机器视觉&#xff0c;医学图像和图像分析应用的快速开发。在欧洲以及日本的工…

【PMP认证考试之个人总结】第 7 章 项目质量管理

第 7章 项目质量管理 《PMP个人备考笔记&#xff08;全篇&#xff09;》下载 7.1 综述 1.六位管理大师的观点区分 ①PDCA循环&#xff1a;由休哈特定义,戴明改进并完善 PDCA 环&#xff08;14 条原则&#xff09;即持续改进&#xff1b; ②朱兰&#xff1a;质量就是适于使用&am…

docker运行jar包_Spring Boot demo系列(五):Docker部署

1 概述本文讲述了如何使用Docker部署Spring Boot应用&#xff0c;首先介绍了Docker的安装过程&#xff0c;接着介绍了Docker的一些基础知识&#xff0c;最后讲述了Dockerfile的编写以及部署过程。2 环境服务器&#xff1a;aarch64 CentOS8JDK&#xff1a;OpenJDK 11Docker&…