C++学习笔记(十五)

在完成对C语言的学习后,我最近开始了对C++和Java的学习,目前跟着视频学习了一些语法,也跟着敲了一些代码,有了一定的掌握程度。现在将跟着视频做的笔记进行整理。本篇博客是整理C++知识点的第十五篇博客。

本篇博客介绍了C++的继承。

本系列博客所有C++代码都在Visual Studio 2022环境下编译运行。程序为64位。

目录

继承

继承的基本语法

继承方式

继承中的对象模型

继承中的构造和析构顺序

继承的同名成员处理

多继承


继承

继承的基本语法

有些时候,类之间具有一定的关系。一些类拥有其他类的共性,和自己的特性。

可以利用继承,减少重复的代码。继承的语法是:

class A: 继承方式 B

继承方式分为public protectedprivate

A类称为子类,或派生类。B类称为父类,或基类。

子类的成员既有父类的成员,也有自己的成员。从父类继承的成员体现了共性,子类自己的成员体现了个性。

#include<iostream>
using namespace std;
class same {
public:
	void show(void) {
		cout << "It is object oriented programming" << endl;
	} 
	void test(void) {
		cout << "Study this is very hard" << endl;
	}

	void thing(void) {
		cout << "It has encapsulation,inheritance and polymorphism" << endl;
	}
};
class Java :public same
{
public:
	void inform(void) {
		cout << "This is Java" << endl;
	}
};

class CPP :public same
{
public:
	void inform(void) {
		cout << "This is C++" << endl;
	}
};

int main(void)
{
	Java learnjava;
	learnjava.inform();
	learnjava.show();
	learnjava.test();
	learnjava.thing();

	CPP learncpp;
	learncpp.inform();
	learncpp.show();
	learncpp.test();
	learncpp.thing();
	return 0;
}

same类有三个成员函数,show成员函数输出It is object oriented programming,test成员函数输出Study this is very hard,thing成员函数输出It has encapsulation,inheritance and polymorphism。Java类以public权限继承了same类,该类自己的成员函数inform输出This is Java。CPP类以public权限继承了same类,该类自己的成员函数inform输出This is C++。

main函数定义了Java类对象learnjava和C++类对象learncpp,分别调用其成员函数,可见子类可以有父类的成员。程序的输出是:

This is Java
It is object oriented programming
Study this is very hard
It has encapsulation,inheritance and polymorphism
This is C++
It is object oriented programming
Study this is very hard
It has encapsulation,inheritance and polymorphism

继承方式

如果类A以public的继承方式继承了类X,那么X的public权限成员在A中仍然为public,X的protected权限成员在A中仍然为protected,X的private权限成员在A中不可访问。

如果类B以protected的继承方式继承了类X,那么X的public权限成员和protected权限成员在A中均为protected,X的private权限成员在A中不可访问。

如果类C以private的继承方式继承了类X,那么X的public权限成员和protected权限成员在A中均为private,X的private权限在A中不可访问。

#include<iostream>
using namespace std;
class base {
public:
	int A;
protected:
	int B;
private:
	int C;
};
class son1 :public base
{
public:
	void func(void) {
		A = 10;
		B = 10;
	}
	void show(void) {
		cout << "A = " << A << endl;
		cout << "B = " << B << endl;
	}
};
class son2 :protected base
{
public:
	void func(void) {
		A = 12;
		B = 12;
	}
	void show(void) {
		cout << "A = " << A << endl;
		cout << "B = " << B << endl;
	}
};
class son3 :private base
{
public:
	void func(void) {
		A = 11;
		B = 11;
	}
	void show(void) {
		cout << "A = " << A << endl;
		cout << "B = " << B << endl;
	}
};

int main(void)
{
	son1 s1;
	s1.func();
	s1.A = 15;
	s1.show();

	son2 s2;
	s2.func();
	s2.show();
	son3 s3;
	s3.func();
	s3.show();
	return 0;
}

base类的成员变量A B C分别为public protected private。子类son1 son2 son3分别以public protected private的方式继承了base类,并且都有func成员函数进行赋值,show成员函数用于输出。main函数中创建了son1 son2 son3类的对象并调用func函数show函数。

程序的输出是:

A = 15
B = 10
A = 12
B = 12
A = 11
B = 11

继承中的对象模型

父类的所有非静态成员属性都会被子类继承,即使子类无法访问,也是被继承了。

#include<iostream>
using namespace std;
class base {
public:
	int A;
protected:
	int B;
private:
	int C;
};

class son :public base
{
public:
	int D;
	void func(void) {
		A = 5;
		B = 10;
		D = 0;
	}
};

int main(void)
{
	son s;
	cout << sizeof(s) << endl;
	return 0;
}


base类有public权限的成员属性A,protected权限的成员属性B,private权限的成员属性C,共三个成员属性。类son以public继承了base,自身还有成员属性D和成员函数func。

main函数创建了son类对象s,并输出其大小。程序的输出是:16

即使son类不可访问C,但是依然继承了C。

继承中的构造和析构顺序

创建子类对象也会调用父类的构造函数。先构造父类再构造子类,析构相反。

#include<iostream>
using namespace std;
class father {
public:
	father() {
		cout << "A" << endl;
	}
	~father() {
		cout << "Z" << endl;
	}
};

class son :public father
{
public:
	son() {
		cout << "a" << endl;
	}
	~son() {
		cout << "z" << endl;
	}
};
int main(void)
{
	son s;
	return 0;
}

father类的构造函数输出A,析构函数输出Z。father类的子类son的构造函数输出a,析构函数输出z。main函数创建了一个son类的对象s。程序的输出是:

A
a
z
Z

继承的同名成员处理

当子类与父类的成员属性同名时,通过子类对象,访问子类的同名成员直接访问即可,访问父类的同名成员则需要加作用域。

如果子类出现和父类同名的成员函数,则子类的成员函数隐藏父类的同名成员函数,访问父类的同名函数需要加作用域。

#include<iostream>
using namespace std;
class father {
public:
	void func() {
		cout << "This is father's func" << endl;
	}
	void func(int num) {
		cout << "This is father's func" << endl;
		cout << "And there is a number = " << num << endl;
	}

	int number = 5;
};
class son :public father
{
public:
	int number = 10;
	void func() {
		cout << "This is son's func" << endl;
	}
};

int main(void)
{
	son s;
	cout << "Son's number is " << s.number << endl;
	cout << "Father's number is " << s.father::number << endl;
	s.func();
	s.father::func();
	s.father::func(100);
	return 0;
}

father类有成员变量number,起始值为5,此外重载了两个func成员函数,一个没有参数,输出This is father's func,另一个接收一个int类型变量,并会输出其值。son类以public的权限继承了father类,内有成员变量number,起始值为10,还有成员函数func输出This is son's func。这样父类和子类出现了成员属性同名和成员变量同名。

main函数创建了son类对象s,并访问其本身和父类的同名成员函数以及同名成员变量。

程序的输出是:

Son's number is 10
Father's number is 5
This is son's func
This is father's func
This is father's func
And there is a number = 100

如果继承时出现了同名静态成员,那么通过子类对象,依然是访问子类的直接访问,访问父类的需要加作用域。

#include<iostream>
using namespace std;
class father {
public:
	static int number;
	static void func(void) {
		cout << "This is father's func" << endl;
	}
};

class son :public father
{
public:
	static int number;
	static void func(void) {
		cout << "This is son's func" << endl;
	}
};

int father::number = 10;
int son::number = 15;

int main(void)
{
	cout << "son's number = " << son::number << endl;
	cout << "father's number = " << son::father::number << endl;
	son s;
	cout << "son's number = " << s.number << endl;
	cout << "father's number = " << s.father::number << endl;

	s.func();
	s.father::func();
	son::func();
	son::father::func();
	return 0;
}

父类father和子类son都有静态成员变量number(都类外赋值),和静态成员函数func(输出不同语句)。main函数通过子类类名和子类对象访问了同名静态成员。程序的输出是:

son's number = 15
father's number = 10
son's number = 15
father's number = 10
This is son's func
This is father's func
This is son's func
This is father's func

多继承

C++允许一个类继承多个类,语法是:

class 子类:继承方式 父类1 继承方式 父类2...{...}

多继承可能导致父类中出现同名成员,需要用作用域区分。实际开发不建议使用多继承。

#include<iostream>
using namespace std;
class father1
{
public:
	int A;
	int C;
};
class father2
{
public:
	int B;
	int C;
};

class son :public father1, public father2
{
public:
	int D;
};
int main(void)
{
	son s;
	s.A = 10;
	s.B = 20;
	s.father1::C = 15;
	s.father2::C = 16;
	s.D = 12;
	cout << "A in father1 is " << s.A << endl;
	cout << "B in father2 is " << s.B << endl;
	cout << "C in father1 is " << s.father1::C << endl;
	cout << "C in father2 is " << s.father2::C << endl;
	cout << "D in son is " << s.D << endl;
	return 0;
}

类father1有成员变量A和C,类father2有成员变量B和C,类son同时继承father1和father2,自身还有成员变量D。main函数创建了son类对象s,并访问其成员。由于son的两个父类都有成员变量C,因此需要用作用域区分。程序的输出是:

A in father1 is 10
B in father2 is 20
C in father1 is 15
C in father2 is 16
D in son is 12
 

如果类B和类C都继承自类A,而类D同时继承类B和类C。那么A的成员变量在B和C中可能有两个值,导致与事实的冲突。

virtual关键字表示虚继承,被虚继承的类是虚基类,这样数据只有一份。

#include<iostream>
using namespace std;
class first {
public:
	int number;
};
class second1 : virtual public first {
};
class second2 :virtual public first {
};
class third : public second1, public second2 {
};
int main(void)
{
	third three;
	three.second1::number = 20;
	cout << three.second1::number << endl;
	cout << three.number << endl;
	three.second2::number = 25;
	cout << three.second2::number << endl;
	cout << three.number << endl;
	return 0;
}

first类有成员变量number,second1和second2对first类进行虚继承,而third类同时继承second1和second2。

main函数创建了third的类对象three,并通过两个不同父类作用域修改number为不同值,这时运行结果:

20
20
25
25
虚继承保证了这种继承的在子类数据的唯一性。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值