(C++)类和对象——继承的基础知识与问题


一、继承的基本语法

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

class Father
{
};

class Son : public Father
{
};

#include <string>
#include <iostream>
using namespace std;

class BasePage
{
public:
	void header()
	{
		cout << "首页、登录、注册(公共头部)" << endl;
	}
	void footer()
	{
		cout << "帮助中心、交流合作、站内地图(公共头部)" <<endl;
	}
	void line()
	{
		cout << "----------------------------------------------" <<endl;
	}
};
class Java: public BasePage
{
public:
	void content()
	{
		cout << "Java" <<endl;
	}
};
class Cpp: public BasePage
{
public:
	void content()
	{
		cout << "Cpp" <<endl;
	}
};
void test01()
{
	Java ja;
	ja.header();
	ja.content();
	ja.footer();
	ja.line();

	Cpp cpp;
	cpp.header();
	cpp.content();
	cpp.footer();
	cpp.line();
}

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

继承的好处:减少重复的代码

子类也成为派生类
父类也成为基类

派生类中的成员包含两大部分:一类是从基类继承过来的,表现派生类与基类的共性。一类是自己增加的成员,表现出自己的个性。


二、继承方式

继承方式


三、继承中的对象模型


#include <string>
#include <iostream>
using namespace std;

class Base
{
public:
	int m_A;
protected:
	int m_B;
private:
	int m_C;
};
class Son :public Base
{
public:
	int m_D;
	//父类中所有非静态成员属性都会被子类继承
	//父类中私有成员是被编译器隐藏了,因此访问不到,但是确实被继承下去了
};

void test01()
{
	cout << sizeof(Son)<<endl;
	//16
}

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

/*
利用开发人员命令提示工具查看对象模型
跳转盘符 F:
跳转文件路径 cd 具体路径下 
查看命名
cl /d1 reportSingleClassLayout类名 文件名
*/

查看后如下显示命令提示工具


四、父类子类中构造与析构的顺序


#include <string>
#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 test01()
{
	Son s;
	//先构造父类,再构造子类,析构则相反
}

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


五、同名成员的处理


#include <string>
#include <iostream>
using namespace std;

class Base
{
public:
	int m_A;
	Base()
	{
		m_A = 100;
	}
	void func()
	{
		cout << "Base func()" <<endl;
	}
	void func(int a)
	{
		cout << "Base func(int a)" <<endl;
	}
};
class Son :public Base
{
public:
	Son()
	{
		m_A = 200;
	}
	int m_A;
	void func()
	{
		cout << "Son func()" <<endl;
	}
};

void test01()
{
	Son s;
	cout << s.m_A <<endl;
	cout << s.Base::m_A <<endl;
}
void test02()
{
	Son s;
	s.func();
	//s.func(1)
	//如果子类中出现和父类同名的成员函数
	//子类的同名成员会隐藏掉父类中所有的同名函数
	//若想要访问隐藏的同名函数,加作用域即可
	s.Base::func(1);
}
int main()
{	
	test02();
	system ("pause");
	return 0 ;
}

总结:
1.子类对象可以直接访问到子类中的同名成员。
2.子类对象加作用域可以访问到父类同名成员。
3.如果子类中出现和父类同名的成员函数,子类的同名成员会隐藏掉父类中所有的同名函数,若想要访问隐藏的同名函数,加作用域即可。


六、同名静态成员处理


#include <string>
#include <iostream>
using namespace std;

class Base
{
public:
	static int m_A;
	static void func()
	{
		cout << "Base Func()" <<endl;
	}
};
int Base::m_A = 100;
class Son :public Base
{
public:
	static int m_A;
	static void func()
	{
		cout << "Son Func()" <<endl;
	}
};
int Son::m_A = 200;
void test01()
{
	//1、通过对象访问
	Son s;
	cout << s.m_A <<endl;
	cout << s.Base::m_A <<endl;
	//2、通过类名访问
	cout << Son::m_A <<endl;
	//第一个 :: 代表通过类名方式访问  
	//第二个 :: 代表访问父类作用域下
	cout << Son::Base::m_A <<endl;
}
void test02()
{
	//访问同名的静态函数
	Son s;
	s.func();
	s.Base::func();

	Son::func();
	Son::Base::func();
}
//静态也适用同名隐藏的规则
int main()
{	
	test01();
	system ("pause");
	return 0 ;
}

总结:同名的静态成员处理方式与非静态成员的处理方式是一样的,只不过有两种访问方式通过对象通过类名


七、多继承语法


#include <string>
#include <iostream>
using namespace std;

class Base1
{
public:
	int m_A;
	Base1()
	{
		m_A = 100;
	}
};
class Base2
{
public:
	int m_A;
	Base2()
	{
		m_A = 200;
	}
};
class Son :public Base1, public Base2
{
public:
	int m_C;
	int m_D;
	Son()
	{
		m_C = 300;
		m_D = 400;
	}
};
void test01()
{
	Son s;
	cout << s.Base1::m_A <<endl;
	cout << s.Base2::m_A <<endl;
	//不建议使用多继承
}
int main()
{	
	test01();
	system ("pause");
	return 0 ;
}

八、菱形继承的问题以及解决方法

在这里插入图片描述


#include <string>
#include <iostream>
using namespace std;

class Animal
{
public:
	int m_Age;
};
//利用虚继承,解决菱形继承的问题
//继承之前加上关键字 virtual
//Animal类称为虚基类
class Sheep : virtual public Animal{};
class Camel : virtual public Animal{};
class Alpaca : public Sheep, public Camel{};
void test01()
{
	Alpaca al;
	al.Sheep::m_Age = 18;
	al.Camel::m_Age = 28;
	//当进行了菱形继承后,两个父类拥有相同数据,需要加以作用域区分
	cout << al.Sheep::m_Age <<endl;
	cout << al.Camel::m_Age <<endl;
	
	//菱形继承导致了数据有两份,资源浪费
	//虚继承之后,资源只有一份,可以直接访问
	cout << al.m_Age << endl;
}
int main()
{	
	test01();
	system ("pause");
	return 0 ;
}

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值