一文带你掌握C++继承

8. C++继承

C++继承

继承遗传学中继承概念,继承的写法,以及继承中的权限问题,继承中的构造函数写法

继承的实质就是父类有的属性在子类中也存在一份。只是根据继承方式不同,在子类中权限的体现不同。

当创建一个类时,您不需要重新编写新的数据成员和成员函数,只需指定新建的类继承了一个已有的类的成员即可。这个已有的类称为基类,新建的类称为派生类

继承代表了 is a 关系。例如,哺乳动物是动物,狗是哺乳动物,因此,狗是动物,等等。

继承:子类没有新的属性或者行为产生

  • 父类

  • 子类

派生:派生类中有新的属性产生

  • 基类

  • 派生类

单继承

只有父类的继承称之为单继承

写法

class 父类
{
    
};
class 子类:继承方式 父类名
{

};
//继承方式就是权限限定词
//公有继承: public
//保护继承: protected
//私有继承: private
class Base
{};
class Derive:public Base//公有继承
{};
class Derive2:protected Base //保护继承
{};
class Derive3:private Base//私有继承
{};
//上面的代码中,Derive,Derive2,Derive3都继承自Base基类
//区别就是继承方式不同

继承中权限问题

publicprotectedprivate
public继承publicprotected不可访问
protected继承protectedprotected不可访问
private继承privateprivate不可访问

综上: 权限限定词只会增强权限(public:最低权限 private:最高权限)

  • public 表示公有继承;
  • private 表示私有继承;
  • protected 表示保护继承;

#include <iostream>
#include <string>
using namespace std;
//父类
class MM 
{
public:
	string getName() { return name; }
	void print() 
	{
		cout << name << "\t" << age << endl;
	}
protected:
	int age=18;
private:
	string name="默认";
};
//子类
//公有继承
class Boy :public MM 
{
public:
	//print()
	void printBoy() 
	{
		//cout << name << endl;  不可能访问
		cout << age << endl;
		print();
	}
protected:
	//int age

private:
	//string name; 不能访问
};
//保护继承
class Girl :protected MM 
{
public:
	void printGirl() 
	{
		cout << age << endl;
		print();
	}
protected:
	//void print()
	//int age;
private:
	//string name;
};
//私有继承
class Son :private MM
{
public:
	void printSon()
	{
		print();
		cout << age << endl;
		//cout << name << endl;				//父类的私有属性子类不能使用
		//只能间接调用父类的非私有方法访问
		cout << getName() << endl;
	}
protected:

private:
	//void print();
	//int age;
	//string name;
};
int main() 
{
	Boy boy;
	boy.print();
	boy.printBoy();

	Girl girl;
	//girl.print();	//无法访问
	girl.printGirl();

	Son son;
	son.printSon();

	return 0;
}

注意点:

  • 继承的属性无论被继承多少次,都存在, A 被B继承 B被C继承 C被D继承 D包含ABC中所有属性
    • 继承不易过多继承,导致子类臃肿
  • 私有继承可以阻断父类属性被孙子类去使用(断子绝孙)

继承中构造函数写法

  • 写法:子类必须先构造父类对象(子类必须调用父类的构造函数) ,调用父类的构造函数必须采用初始化参数列表
  • 构造和析构顺序问题
#include <iostream>
#include <string>
using namespace std;
class A 
{
public:
	A() 
	{
		cout << a;
	}
	A(string a):a(a)
	{
		cout << a;
	}
	~A() 
	{
		cout << a;
	}
protected:
	string a="A";
};
class B :public A
{
public:
	B()					//就算没写,也会调用父类的无参构造函数		
	{
		cout << b;
	}
	//子类完整写法: 除了初始化自身数据,还需要初始化父类数据
	B(string a, string b) :A(a)
	{
		this->b = b;	//自身属性可以采用初始化列表
		cout << b;
	}
	void print() 
	{
		cout << a;
		cout << b;
	}
	~B() 
	{
		cout << b;
	}
protected:
	string b = "B";
};
class C :public B 
{
public:
	C(string a, string b, string c) :B(a, b), c(c) 
	{
		cout << c;
	}
	void print() 
	{
		cout << a << b << c << endl;
	}
	~C() 
	{
		cout << c;
	}
protected:
	string c;
};
int main() 
{
	{
		B b;
		cout << endl;
		B object("A", "B");
		cout << endl;
		object.print();
		cout << endl;
		C c("A","B","C");
		cout << endl;
		c.print();
	}
	cout << endl;
	{
		cout << "构造和析构顺序问题:" << endl;
		C cobject("A", "B", "C");
		//ABCCBA
	}
	return 0;
}

多继承

多继承就是存在两个以及两个以上父类

  • 权限问题和构造函数和单继承一样的
#include <iostream>
#include <string>
using namespace std;
class Father 
{
public:
	Father(string FFName) :FFName(FFName) {}
protected:
	string FFName;
};
class Monther 
{
public:
	Monther(string MFName) :MFName(MFName) {}
protected:
	string MFName;
};
class Son :public Father, public Monther 
{
public:
	Son(string FFName, string MFName, string SSName) :Father(FFName),Monther(MFName)
	{
		this->SFName = FFName + MFName;
		this->SSName = SSName;
	}
	void print() 
	{
		cout << FFName << endl;
		cout << MFName << endl;
		cout << this->SFName + this->SSName << endl;
	}
protected:
	string SFName;
	string SSName;
};
int main() 
{
	Son son("李","田","大牛");
	son.print();
	return 0;
}

菱形继承


菱形继承是因为多继承存在问题而衍生的继承方式(菱形继承就是虚继承)

(题目可能会出现,但是自己写代码不会出现)

#include <iostream>
#include <string>
using namespace std;
class A 
{
public:
	A(int a) :a(a) {}
	int a=666;
};
class B :virtual public A
{
public:
	B(int a) :A(a) {}
};
class C :virtual public A
{
public:
	C(int a) :A(a) {}
};

class D :public C, public B      //多继承构造顺序只和这个地方顺序(继承顺序)有关
{
public:
	D(int a) : C(14), B(12) ,A(a)     //子类必须调用爷爷构造函数
	{

	}
	void print() 
	{
		cout << A::a << endl;	
		cout << B::a << endl;	
		cout << C::a << endl;	
	}
};
int main() 
{
	D dobject(23);
	dobject.print();

	return 0;
}

继承中同名问题

  • 数据成员同名
  • 成员函数同名
#include <iostream>
#include <string>
using namespace std;
class MM 
{
public:
	MM(string name) :name(name) {}
	void print() 
	{
		cout << "-------------------------" << endl;
		cout << "MM::name" << endl;
		cout << "-------------------------" << endl;
	}
protected:
	string name;
};
class Son :public MM 
{
public:
	Son() :name("Son"), MM("MM")
	{

	}
	void print() 
	{
		cout << "-------------------------" << endl;
		cout << "Son::name" << endl;
		//No.1 不写任何标识 ,就近原则
		cout << name << endl;
		//No.2 可以用类名
		cout << MM::name << endl;
		cout << "-------------------------" << endl;
	}
protected:
	string name;
};

void printInfo(MM* p) 
{
	p->print();
}
int main() 
{
	//对象访问:
	//No.1 不写任何标识 ,就近原则
	Son son;
	son.print();
	son.MM::print();
	son.Son::print();
	MM mm("MM");
	mm.print();
	//指针访问
	//正常初始化访问
	cout << "正常初始化指针访问" << endl;
	Son* pSon = new Son;
	pSon->print();
	MM* pMM = new MM("MM");
	pMM->print();
	//非正常初始化访问
	//1.1 父类指针用子类对象初始化
	//在没有写任何修饰词的,看指针类型
	MM* pFather = new Son;
	pFather->print();				//调用那个函数?
	//1.2 子类指针被父类对象初始化,危险,一般不这样做
	//Son* pp = new MM("MM");		//错误的
	Son* pp = NULL;
	pp = static_cast<Son*>(&mm);	//强制类型转换类似C语言强制
	//pp->print();					//程序中断,没办法执行
	cout << "当父类指针成为函数参数时候,传参子类和父类对象通用" << endl;
	printInfo(pMM);
	printInfo(pSon);
	return 0;
}
  • 4
    点赞
  • 5
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
Eclipse是一个开放源代码的集成开发环境(IDE),可用于Java开发,但也可以用于其他编程语言的开发。在本中,我将向你展示如何使用Eclipse进行Java开发。 1. 下载Eclipse 首先,你需要从Eclipse官方网站下载Eclipse IDE。下载页面上将提供几个不同的版本,包括Eclipse IDE for Java Developers、Eclipse IDE for JavaScript and Web Developers,以及Eclipse IDE for C/C++ Developers等。选择适合你的版本,然后按照安装向导进行安装。 2. 创建Java项目 一旦你安装了Eclipse,你可以启动它并创建一个新的Java项目。选择“File”->“New”->“Java Project”,然后按照向导创建一个新的Java项目。在创建项目时,你需要指定项目名称、项目类型以及JRE版本等信息。 3. 创建Java类 一旦你创建了一个Java项目,你就可以创建一个Java类。选择你的Java项目,在“src”件夹上右键单击,然后选择“New”->“Class”。输入类名和选择要继承的类(如果有的话),然后点击“Finish”。 4. 编写Java代码 现在你已经创建了一个Java类,可以开始编写Java代码了。在Eclipse的编辑器中,你可以输入Java代码并保存它。当你保存Java件时,Eclipse会自动编译你的代码,并在Problems视图中显示任何编译错误。 5. 运行Java程序 一旦你编写了Java代码并保存了它,你可以运行Java程序。右键单击Java件,然后选择“Run As”->“Java Application”。如果一切顺利,你的Java程序将在控制台中输出结果。 6. 调试Java程序 如果你的Java程序出现了错误或不按预期运行,你可以使用Eclipse的调试器来调试它。在Eclipse的编辑器中,你可以设置断点并启动调试器。当程序执行到断点时,调试器会暂停程序并允许你检查变量、运行代码等。 7. 导入外部JAR包 有时,你可能需要使用外部JAR包来完成你的Java项目。在Eclipse中,你可以简单地将外部JAR包导入到你的项目中。右键单击Java项目,然后选择“Build Path”->“Configure Build Path”。在“Libraries”选项卡上,你可以添加外部JAR包。 总结 在本中,我们介绍了如何使用Eclipse进行Java开发。我们学习了如何创建Java项目、创建Java类、编写Java代码、运行Java程序、调试Java程序以及导入外部JAR包。Eclipse具有强大的功能,可以大大提高Java开发的效率。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值