【C++】继承


在这里插入图片描述

1.继承的引出

网站类

//新闻类
class News
{
    public:
    	void header() {
            cout<<"公共头部"<<endl;
        }
    	void footer() {
            cout<<"公共底部"<<endl;
        }
    	void left() {
            cout<<"左侧列表"<<endl;
        }
    	void content() {
            cout<<"新闻播放"<<endl;
        }
};
//娱乐类
class YULE
{
    public:
    	void header() {
            cout<<"公共头部"<<endl;
        }
    	void footer() {
            cout<<"公共底部"<<endl;
        }
    	void left() {
            cout<<"左侧列表"<<endl;
        }
    	void content() {
            cout<<"火西肆。。。。"<<endl;
        }
};

两种类重复的地方比较多,可以将重复的地方抽象到一个基类上

1.1继承的写法
//基类
class BasePage
{
    public:
    	void header() {
            cout<<"公共头部"<<endl;
        }
    	void footer() {
            cout<<"公共底部"<<endl;
        }
    	void left() {
            cout<<"左侧列表"<<endl;
        }
};
//继承的写法
class News :public BasePage //News类继承于BasePage类
{
    public:
    	void content() {
            cout<<"新闻播放"<<endl;
        }
}
class Game:public BasePage //Game类继承于BasePage类
{
     public:
    	void content() {
            cout<<"战地5直播。。。"<<endl;
        }
}

在上面的例子中:BasePage叫做基类(父类),News/Yule/Game叫做子类(派生类)

2.继承方式

**语法:**class 子类: 继承方式 父类 (如上面例子的class News : public BasePage)

继承方式图例
image-20220605195258182

无论什么继承方式,父类中的私有属性都无法被派生类访问。

在这里插入图片描述

3.继承中的对象模型

class  A
{
public:
	int a;
protected:
	int b;
private:
	int c;
};//A类对象大小为12
class B :public A
{
public:
	int m_d;
};
void func()
{
	B b;
	C c;
	D d;
	cout << sizeof(b) << endl;
}
//输出:16

结果输出为16,说明了父类的private成员被派生类继承,但是被编译器隐藏所以无法访问

4.继承中的构造和析构顺序

class  Parent
{
public:
	Parent() {
		cout << "构造Parent类" << endl;
	}
	~Parent()
	{
		cout << "析构Parten类" << endl;
	}
	int a;
protected:
	int b;
private:
	int c;
};
class Son :public Parent 
{
public:
	Son()
	{
		cout << "构造Son类" << endl;
	}
	~Son()
	{
		cout << "析构Son类" << endl;
	}
	int m_d;
};
int main()
{
	Son s;
	return 0;
}

image-20220605204813784

子类会继承父类的成员属性和成员函数

但是子类不好继承父类的构造函数和析构函数

4.1当父类没有默认构造函数时
class  Parent
{
public:
	Parent(int a) {
		_a = a;
	}
	~Parent(){}
	int _a;
protected:
	int b;
private:
	int c;
};
class Son :public Parent 
{
public:
	Son(int a,int d=10):Parent(a){
		m_d = d;
	}
	~Son(){}
	void Print()
	{
		cout << this->_a <<" "<< this->m_d << endl;
	}
	int m_d;
};
int main()
{
	Son s(5);
	s.Print();
	return 0;
}

当父类不存在默认构造函数时,需要派生类在初始化列表的位置显示调用父类的构造函数

输出5 10

image-20220605215600696

在这里插入图片描述

5.继承中的成员处理

5.1继承中的同名成员处理
class  Parent
{
public:
	Parent() {
		_a = 10;
	}
	~Parent()
	{}
    void func(){
        cout<<this._a<<endl;
    }
	int _a;
};
class Son :public Parent 
{
public:
	Son() {
		_a = 20;
	}
    void func(){
        cout<<this._a<<endl;
    }
	int _a;
};
Son s;
cout << s._a << endl;

输出结果为:20

根据就近原则,先调用子类的同名成员

但是如果想要调用父类的同名成员?方式:调用作用域

cout << s.Parent::_a << endl;
//输出为10
  • 如果子类和父类拥有同名的函数和成员,子类不会覆盖父类的成员和函数,只是加上作用域隐藏;

  • 调用规则满足就近原则,如果想要调用父类,加上作用域调用。

5.2继承中静态成员的处理

首先类的静态成员和静态成员函数属于整个类,位于静态区。

class  Parent
{
public:
	int _a;
	static int m_st;
};
int Parent::m_st = 50;
class Son :public Parent 
{
public:
	int _a;
	static int m_st;
};
int Son::m_st = 60;
int main()
{
	Son s;
	cout <<"Parent m_st:"<<Parent::m_st<<"Son m_st"<<Son::m_st <<"Son::Parent::m_st"<<Son::Parent::m_st<< endl;
	return 0;
}

输出:Parent m_st:50 Son m_st:60 Son::Parent::m_st:50

5.3非自动继承的成员函数

不是所有的函数都可以自动从基类继承到派生类中。比如基类的构造函数和析构函数;另外operator=也不能被继承,因为它完成类似构造函数的行为。

在继承的过程中,如果没有创建这些函数,编译器会自动生成它们。

6.多继承问题

我们可以同时从多个类继承。但是多继承是饱受争议的,从多个类继承可能会导致函数、变量等同名导致较多的歧义。需要加上作用域

**语法:**class 类名: 继承方式一:父类1,继承方式二,父类2…

6.1菱形继承和虚继承

两个派生类继承同一个基类,而又有某个类同时继承两个派生类,这种继承方式就被称为菱形继承

image-20220605222347877

菱形继承带来的问题

这里羊继承了动物的数据和函数,驼也继承了动物类的数据和函数,羊驼调用数据和函数时就会出现二义性。

解决方案:虚继承

class animal{
    public:
    	int m_age;
};
//虚基类
class sheep:virtual public animal{
    
};
//虚基类
class tuo:virtual public animal{
    
};
class sheeptuo:public sheep,public tuo{
    
};
//最后就只剩下一份数据和函数

在菱形继承内部结构中,如这里的sheeptuo类的内部结构

  • 1.内容有虚基类指针
  • 2.虚基类指针指向一张虚基类表
  • 3.通过虚基类表可以找到偏移量
  • 4.找到公共的成员
int main()
{
    sheeptuo st;
    cout << sizeof(st) << endl;
    return 0;
}

输出的结果为:12

分别存放了sheep类的虚基类指针< vbptr >和tuo类的虚基类指针< vbptr >

image-20220605231230302

非虚基类继承

class animal {
public:
    int m_age;
};
class sheep : public animal {

};
class tuo : public animal {

};
class sheeptuo :public sheep, public tuo {

};
int main()
{
    sheeptuo st;
    cout << sizeof(st) << endl;
    return 0;
}
//输出:8

image-20220605231819744
在这里插入图片描述

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

影中人lx

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值