0
点赞
收藏
分享

微信扫一扫

【C++初阶】继承

飞空之羽 2022-01-26 阅读 67

目录

继承的概念和定义

继承中的作用域

派生类的默认成员函数

构造函数:

析构函数:

赋值&析构函数

复杂的菱形继承及菱形虚拟继承

继承的总结和反思


继承的概念和定义

class Person
{
public:
	void Print()
	{
		cout << "name:" << _name << endl;
		cout << "age:" << _age << endl;
	}
protected:
	string _name = "peter";
	int _age = 18;
};
//Student继承了Person,Student中就拥有了Person的成员
//person 叫父类/基类
//student叫子类/派生类
class Student :public Person
{
protected:
	int _stuid;
};
class Teacher :public Person
{
protected:
	int _Jobid;
};
int main()
{
	Student s;
	Teacher t;
	s.Print();
	t.Print();
	return 0;
}

继承中的作用域

//A和B类的两个fun构成隐藏关系,继承中函数名相同就是隐藏
class  A
{
public:
	void fun()
	{
		cout << "func()" << endl;
	}
};
class B :public A
{
public:
	void fun(int i)
	{}
};
void Test()
{
	B b;
	b.fun(10);
	b.fun();
	//想调用父类的=>b.A::fun()
}
int main()
{
	Test();
	return 0;
}

派生类的默认成员函数

构造函数:

class Person
{
public:
	//Person(const char* name = "peter")
	Person(const char* name )
		: _name(name)
	{
		cout << "Person()" << endl;
	}
	Person(const Person& p)
		: _name(p._name)
	{
		cout << "Person(const Person& p)" << endl;
	}
	Person& operator=(const Person& p)
	{
		cout << "Person operator=(const Person& p)" << endl;
		if (this != &p)
			_name = p._name;
		return *this;
	}
	~Person()
	{
		cout << "~Person()" << endl;
	}
protected:
	string _name; // 姓名
};
class Student :public Person
{
public:
	//子类构造函数——我们不写,编译器默认生成
	//1.继承的父类成员---作为一个整体调用父类的构造函数初始化
	//2.自己的内置类型成员---不处理(除非给了缺省值)
	//3.自己的自定义类型成员---调用它的默认构造函数

	//我们要自己实现子类构造函数
	Student(const char*name, int id, const char* address)
	//要注意的是父类成员是作为一个整体,调用父类的构造函数进行初始化
	:Person(name)
	, _id(id)
	, _address(address)
	{}
private:
	int _id;//内置类型
	string _address;//自定义类型
};
int main()
{
	Student s("黄振盛",1,"厦门市");
	return 0;
}

析构函数:

class Person
{
public:
	Person(const char* name = "peter")
	//Person(const char* name )
		: _name(name)
	{
		cout << "Person()" << endl;
	}
	Person(const Person& p)
		: _name(p._name)
	{
		cout << "Person(const Person& p)" << endl;
	}
	Person& operator=(const Person& p)
	{
		cout << "Person operator=(const Person& p)" << endl;
		if (this != &p)
			_name = p._name;
		return *this;
	}
	~Person()
	{
		cout << "~Person()" << endl;
	}
protected:
	string _name; // 姓名
};
class Student :public Person
{
public:
	//子类拷贝构造函数——我们不写,编译器默认生成
	//1.继承的父类成员作为一个整体---调用父类的拷贝构造
	//2.自己的内置类型成员---调用它的拷贝构造
	//3.自己的自定义类型成员---值拷贝
	Student(const char*name, int id, const char* address)
		//要注意的是父类成员是作为一个整体,调用父类的构造函数进行初始化
		:Person(name)
		, _id(id)
		, _address(address)
	{}
	//自己实现拷贝构造
	Student(const Student& s)
		:Person(s)
		,_id(s._id)
		, _address(s._address)
	{}
private:
	int _id;//内置类型
	string _address;//自定义类型
};
int main()
{
	Student s1("小红",100,"厦门市");
	Student s2(s1);
	return 0;
}

赋值&析构函数

class Person
{
public:
	//Person(const char* name = "peter")
	Person(const char* name )
		: _name(name)
	{
		cout << "Person()" << endl;
	}
	Person(const Person& p)
		: _name(p._name)
	{
		cout << "Person(const Person& p)" << endl;
	}
	Person& operator=(const Person& p)
	{
		cout << "Person operator=(const Person& p)" << endl;
		if (this != &p)
			_name = p._name;
		return *this;
	}
	~Person()
	{
		cout << "~Person()" << endl;
	}
protected:
	string _name; // 姓名
};
class Student :public Person
{
public:
	//子类拷贝构造函数——我们不写,编译器默认生成
	//1.继承的父类成员作为一个整体---调用父类的拷贝构造
	//2.自己的内置类型成员---调用它的拷贝构造
	//3.自己的自定义类型成员---值拷贝
	Student(const char*name, int id, const char* address)
		//要注意的是父类成员是作为一个整体,调用父类的构造函数进行初始化
		:Person(name)
		, _id(id)
		, _address(address)
	{}
	自己实现拷贝构造
	//Student(const Student& s)
	//	:Person(s)
	//	,_id(s._id)
	//	, _address(s._address)
	//{}
	//赋值:
	Student& operator = (const Student& s)
	{
		if (this != &s)
		{
			_id = s._id;
			_address = s._address;
			Person::operator = (s);
		}
		return *this;
	}
	//析构
	//子类拷贝构造函数——我们不写,编译器默认生成
	//1.继承的父类成员作为一个整体---调用父类的析构函数
	//2.自己的内置类型成员---不处理
	//3.自己的自定义类型成员---调用它的析构函数
	//自己实现
	//子类析构函数和父类析构函数构成隐藏关系--why?
	//因为编译器会对析构函数名做特殊处理,所有类的析构函数都会被统一处理成destructor()
	//为什么编译器会做这个处理呢?——析构函数要构成多态重写
	~Student()
	{
		Person::~Person();//子类的析构函数在执行结束后会自动调用父类的析构函数
	}
private:
	int _id;//内置类型
	string _address;//自定义类型
};
int main()
{
	Student s1("小红",100,"厦门市");
	Student s2(s1);
	Student s3("小蓝",200,"泉州市");
	s1 = s3;
	return 0;
}

复杂的菱形继承及菱形虚拟继承

先来看一段代码:

class B : public A
{
public:
	int _b;
};
// class C : public A
class C : public A
{
public:
	int _c;
};
class D : public B, public C
{
public:
	int _d;
};
int main()
{
	D d;
	d.B::_a = 1;
	d.C::_a = 2;
	d._b = 3;
	d._c = 4;
	d._d = 5;
	//d._a = 0;
	return 0;
}

 再看一段虚继承代码:

class A
{
public:
	int _a;
};
// class B : public A
class B : virtual public A
{
public:
	int _b;
};
// class C : public A
class C : virtual public A
{
public:
	int _c;
};
class D : public B, public C
{
public:
	int _d;
};
int main()
{
	D d;
	d.B::_a = 1;
	d.C::_a = 2;
	d._b = 3;
	d._c = 4;
	d._d = 5;
	d._a = 0;
	return 0;
}

 将上面两段内存代码对比如下:

 

继承的总结和反思

举报

相关推荐

0 条评论