01 继承的基本语法 

02 继承方式

03 继承中的对象属性

04 继承中构造和析构顺序

05 继承中同名成员的处理

06 继承中同名静态成员处理

07 多继承语法

08 菱形继承

 

01 继承的基本语法 

#include<iostream>
using namespace std;
//继承实现页面
//公共类页面
class Public
{
public:
	void heard()
	{
		cout << "首页、公开课、登录、注册... (公共头部)" << endl;
	}
	void bottom()
	{
		cout << "帮助中心、交流合作、站内地图... (公共底部)"<<endl;
	}
	 
		
	void left()
	{
		cout << "Java、Python、 C++、... (公共分类列表)" << endl;
	}

	
};
//继承好处:减少代码重复
//语法: class子类: 继承方式
//子类 也称为 派生类
//父类 也称为 基类
//java页面

class Java : public Public
{
public:

	void self()
	{
		cout << "java视频" << endl;
	}
};

//python页面

class Python : public Public
{
public:
	void self()
	{
		cout << "python视频" << endl;
	}
};

//c++页面

class Cpp : public Public
{
public:
	void self()
	{
		cout << "c++视频" << endl;
	}
};

void test()
{
	Java j;
	j.bottom();
	j.heard();
	j.left();
	j.self();
	cout << "----------------------"  << endl;

	Python p;
	p.bottom();
	p.heard();
	p.left();
	p.self();
	cout << "----------------------" << endl;

	Cpp c;
	c.bottom();
	c.heard();
	c.left();
	c.self();
}
int main()
{
	test();
	system("pause");
	return 0;
}

//总结:
//派生类中的成员,包含两大部分:
//-类是从基类继承过来的, - 类是自己增加的成员。
//从基类继承过过来的表现其共性,而新增的成员体现了其个性。

02 继承方式

#include<iostream>
using namespace std;
class C1
{
public:
	int a;
protected:
	int b;
private:
	int c;
};

//1.公共继承
class J1 : public C1
{
public:
	void func()
	{
		a = 100;	//父类中的公共权限成员 到子类中依然是公共权限
		b = 200; //父类中的保护权限成员 到子类中依然是保护权限
		//c = 300; //父类中的私有权限成员 到子类中访问不到
	}
	
};

void test1()
{
	J1 j;
	j.a = 1000;
	//j.b = 2000; 到子类中,B是保护权限类外访问不到
}


class C2
{
public:
	int a;
protected:
	int b;
private:
	int c;
};
//2.保护继承
class J2 : protected C2
{
public:
	void test()
	{
		a = 200; //父类中的公共权限成员 到子类中是保护权限
		b = 300; //父类中的保护权限成员 到子类中依然是保护权限
		//c = 400;//父类中的私有权限成员 到子类中访问不到
	}

};

void test2()
{
	J2 j;
	//j.a = 100; //在J2中a变成保护权限,因此类外访问不到
	//b = 2000; //在J2中b变成保护权限,访问不到

}

class C3
{
public:
	int a;
protected:
	int b;
private:
	int c;
};

//3.私有继承
class J3 :private C3
{
public:
	void test()
	{
		a = 200; //父类中的公共权限成员 到子类中是私有权限
		b = 300; //父类中的保护权限成员 到子类中是私有权限
		//c = 400; //父类中的私有权限成员 到子类中访问不到
	}

};

void test3()
{
	J3 j;
	//a = 200; 到J3中,变成私有成员,到类外访问不到
	//b = 300; 到J3中,变成私有成员,到类外访问不到

}

class GrandSon : public J3
{
	void test()
	{
		//a = 200;//到了J3中,a变成私有,即使是儿子,也是访问不到
		//b = 300; //到了J3中, b变成私有, 即使是儿子, 也是访问不到

	}
};

int main()
{
	system("pause");
	return 0;
}

03 继承中的对象属性

#include<iostream>
using namespace std;
class Base
{
public:
	int a;
protected:
	int b;
private:
	int c;
};

class Son : public Base
{
public:
	int d;
};

void test()
{
	Son s;
	//内存空间16
	//父类中所有非静态成员属性都会被子类继承下去
	//父类中私有成员属性是被编译器给隐藏了,因此访问不到,但是确实被继承下去了

	cout << "Son内存空间大小为:" << sizeof(s) << endl;
}

int main()
{
	test();
	system("pause");
	return 0;
}
//利用开发人员命令提示工具查看对象类型
//跳转文件路径, cd 具体路径下
//查看命名dir
//cl /d1 reportSingleClassLayout类名 文件名(c1 字母l,d1数字1)

1.打开Developer Command Prompt for VS 201


 

2.  cd C:\Users\yys53\OneDrive\c\c++\继承\继承

dir

3. cl /d1 reportSingleClassLayout类名 文件名

cl /d1 reportSingleClassLayoutSon '.\03 继承中的对象属性.cpp'

(输入03 后按tab自动补全)

04 继承中构造和析构顺序

#include<iostream>
using namespace std;

class Base
{
public:
	Base()
	{
		cout<<"Base构造函数"<<endl;
	}
	~Base()
	{
		cout << "Base的析构函数" << endl;

	}
};

class Son :public Base
{
public:
	Son()
	{
		cout << "Son的构造函数" << endl;

	}
	~Son()
	{
		cout << "Son的析构函数" << endl;
	}
};

void test()
{
	//继承中的构造和析构的顺序如下
	//先构造父类,载构造子类,析构的顺序与构造的顺序相反

	//Base();
	Son();

}
int main()
{
	test();
	system("pause");
	return 0;
}

 

05 继承中同名成员的处理

#include<iostream>
using namespace std;

class Base
{
public:
	Base()
	{

		a = 10;
	}
	void func()
	{
		cout << "Base的函数调用" << endl;
	}
	void func(int a)
	{
		cout << "Base的int函数调用" << endl;
	}
	int a;
};

class Son :public Base
{
public:
	Son()
	{
		a = 400;
	}
	void func()
	{
		cout << "Son的函数" << endl;
	}
	
	int a;

	
};
//同名成员属性的处理
void test()
{
	Son s;
	cout << "Son的a=" << s.a << endl; 
	//如果通过子类对象,访问到父类同名成员,需要加作用域
	cout << "Base的a=" << s.Base::a << endl;


}
//同名成员函数的处理
void test2()
{
	Son s;
	s.func();//直接调用,调用的子类中同名成员
	s.Base::func();
	//s.func(100);当子类中出现和父类同名成员函数同名时,子类同名成员会屏蔽父类中所有成员函数
	//如果想访问到父类中被屏蔽的同名成员函数,需要加作用域

	s.Base::func(100);
}
int main()
{
	//test();
	test2();
	system("pause");
	return 0;
}

06 继承中同名静态成员处理

#include<iostream>
using namespace std;

class Base
{
public:
	static void func()
	{
		cout << "Base静态函数调用" << endl;
	}
	static void func(static int a)
	{
		cout << "Base静态函数int的调用" << endl;
	}
	static int a;
	

};

int Base::a = 100;
class Son :public Base
{
public:
	static void func()
	{
		cout << "son静态函数调用" << endl;
	}
	static int a;
	

};

int Son::a = 200;
//同名静态成员属性的处理
void test()
{
	//1.通过对象访问.
	Son s;
	cout << "对象访问Son下a=" << s.a << endl;
	cout << "对象访问Base下a=" << s.Base::a << endl;
	//2.通过类名访问
	cout << "类名访问Son下a=" << Son::a << endl;
	//第一个::代表通过类名方式访问, 第二个::代表访问父类作用域下

	cout << "类名访问Base下a=" << Son::Base::a << endl;
}
//同名静态成员函数的处理
void test2()
{
	Son s;
	//通过对象访问
	cout << "通过对象" << endl;
	s.func();
	s.Base::func();
	cout << "通过类名" << endl;
	Son::func();
	Son::Base::func();
	//子类出现和父类同名的静态成员函数,也会隐藏父类所以同名成员函数
	//如果想访问父类中被隐藏的同名成员,需要加作用域

	Son::Base::func(200);
}
int main()
{
	//test();
	test2();
	system("pause");
	return 0;
}

07 多继承语法

#include<iostream>
using namespace std;

class Base1
{
public:
	Base1()
	{
		a = 200;
	}
	int a;
};

class Base2
{
public:
	Base2()
	{
		a = 400;
	}
	int a;
};
//子类 需要继承base1和Base2
//语法:class 子类:继承方式 父类1,继承方式 父类2
class Son : public Base1, public Base2
{
public:
	Son()
	{
		c = 2000;
		d = 5000;
	}
	int c;
	int d;
};

void test1()
{
	Son s;
	cout << "Son的内存空间大小为:" << sizeof(s) << endl;
	//当多个父类中出现同名成员,需要加作用域区分,所以开发者不太建议多继承
	cout <<"Base1的a=" << s.Base1::a << endl;
	cout << "Base2的a=" << s.Base2::a << endl;

}
int main()
{
	test1();
	system("pause");
	return 0;
}

08 菱形继承

#include<iostream>
using namespace std;
//动物类
class Animal
{
public:
	
	int age;
	
};
//利用虚继承 解决菱形继承问题
//养类
class Sheep:virtual public Animal{};
//驼类
class Tuo: virtual public Animal{};
//羊驼类
class SheepTuo: public Sheep, public Tuo{};


void test1()
{
	SheepTuo st;
	st.Sheep::age = 20;
	st.Tuo::age = 30;
	st.age = 60;
	//当菱形继承,两个父类拥有相同数据,需要加以作用域区分
	cout << "st.Sheep::age=" << st.Sheep::age << endl;
	cout << "st.Tuo::age=" << st.Tuo::age << endl;
	//这份数据我们知道 只有一份就可以, 菱形继承导致数据有两份,资源浪费
	cout << "st.age=" << st.age << endl;
}

int main()
{
	test1();
}
//总结:
//菱形继承带来主要问题类继承两份相同数据,导致资源浪费以及毫无意义
//利用虚继承可以解决菱形继承问题

情形一:不用virtual

C:\Users\yys53\OneDrive\c\c++\继承\继承>cl /d1 reportSingleClassLayoutSheepTuo "08 菱形继承.cpp"

08 菱形继承.cpp

class SheepTuo  size(8):
        +---
 0      | +--- (base class Sheep)
 0      | | +--- (base class Animal)
 0      | | | age
        | | +---
        | +---
 4      | +--- (base class Tuo)
 4      | | +--- (base class Animal)
 4      | | | age
        | | +---
        | +---
        +---

情形二:用virtual
C:\Users\yys53\OneDrive\c\c++\继承\继承>cl /d1 reportSingleClassLayoutSheepTuo "08 菱形继承.cpp"

 

08 菱形继承.cpp

class SheepTuo  size(12):
        +---
 0      | +--- (base class Sheep)
 0      | | {vbptr}
        | +---
 4      | +--- (base class Tuo)
 4      | | {vbptr}
        | +---
        +---
        +--- (virtual base Animal)
 8      | age
        +---

SheepTuo::$vbtable@Sheep@:
 0      | 0
 1      | 8 (SheepTuod(Sheep+0)Animal)

SheepTuo::$vbtable@Tuo@:
 0      | 0
 1      | 4 (SheepTuod(Tuo+0)Animal)
vbi:       class  offset o.vbptr  o.vbte fVtorDisp
          Animal       8       0       4 0