C/C++————继承

C/C++————继承

继承

1.继承是什么?

在 C++ 中,继承(Inheritance) 是面向对象编程(OOP)的核心特性之一,允许一个类从另一个类派生,继承其属性(成员变量)和行为(成员函数),从而实现代码复用和多态性。子类——派生类,父类——基类

基本语法

class 父类名 {

public:

int a;

void show() {

std::cout << "This is base class" << std::endl;

}

};

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

public:

int b;

void display() {

std::cout << "This is derived class" << std::endl;

}

};

三种继承方式

继承方式语法示例父类的 public 成员在子类中protected 成员private 成员public 继承class B : public A保持 public保持 protected不可访问protected 继承class B : protected A变成 protected保持 protected不可访问private 继承class B : private A变成 private变成 private不可访问

1)public继承

#include

using namespace std;

class base1

{

public:

int m_a;

protected:

int m_b;

private:

int m_c;

};

class son:public base1

{

public:

void func()

{

m_a;//父类中的公共权限成员 到子类中依然是公共权限

m_b;//父类中的保护权限成员 到子类中依然是保护权限

//m_c,父类中的私有权限成员 到子类中依然是私有权限,访问不到

}

};

void test_01()

{

son s1;

s1.m_a=12;

cout<

s1.func();

}

int main()

{

test_01();

return 0;

}

public继承在子类里面,可以对父类public,protected变量进行访问修改

在子类外,仅能对public修改,而protected不行,如上代码所示

2)protected继承

#include

using namespace std;

class base1

{

public:

int m_a;

protected:

int m_b;

private:

int m_c;

};

class son:protected base1

{

public:

void func()

{

m_a;//父类中的公共权限成员 到子类中变成保护权限

m_b;//父类中的保护权限成员 到子类中变成保护权限

//m_c,父类中的私有权限成员 到子类中依然是私有权限,访问不到

}

};

void test_01()

{

son s1;

//s1.m_a=12;已变为protected不可访问编辑

//s1.m_b=20;protected不可访问编辑

}

int main()

{

return 0;

}

protected继承在子类里面,可以对父类public(变为protected类型),protected变量进行访问修改

在子类外,对public,protected都不行(都已是protected类型),如上代码所示

3)private继承

#include

using namespace std;

class base1

{

public:

int m_a;

protected:

int m_b;

private:

int m_c;

};

class son:private base1

{

public:

void func()

{

m_a=10;//父类中的公共权限成员 到子类中变成私有权限

m_b=10;//父类中的保护权限成员 到子类中变成私有权限

//m_c,父类中的私有权限成员 到子类中依然是私有权限,访问不到

}

};

class gdson:public son

{

public:

void func()

{

//m_a访问不到,已经变为私有

}

};

int main()

{

return 0;

}

private继承在子类里面,可以对父类public,protected变量进行访问修改

在子类外,对public,protected都不行(都已是private类型)

在对私有继承再继承时,都不能访问并编辑(都已是private类型),如上代码所示

2.继承中构造与析构顺序

在我们学习了三种继承方式,你是否会有疑问?——类中有构造与析构函数,那么继承中他们顺序是怎么样的,这一下小节我们就来探讨一下

#include

using namespace std;

class base

{

public:

base()

{

cout<<"父类构造函数"<

}

~base()

{

cout<<"父类析构函数"<

}

};

class son:public base

{

public:

son()

{

cout<<"子类构造函数"<

}

~son()

{

cout<<"子类析构函数"<

}

};

void test_01()

{

son s1;

}

int main()

{

test_01();

return 0;

}

输出结果如下:

我们可以看到顺序是——父->子->子->父

3.继承同名成员处理方式

1)同名成员变量处理

在遇到父子类都有相同名的变量时,该如何正确访问呢,如下代码所示:

class base

{

public:

base()

{

m_a=100;

}

int m_a;

};

class son:private base

{

public:

son()

{

m_a=200;

}

int m_a;

};

我们先进行简单测试一下:

#include

using namespace std;

class base

{

public:

base()

{

m_a=100;

}

int m_a;

};

class son:public base

{

public:

son()

{

m_a=200;

}

int m_a;

};

void test_01()

{

son s1;

cout<

}

int main()

{

test_01();

return 0;

}

最后输出结果是200,“那我想访问父类的m_a该怎么做呢?”,其实我们只要加一作用域就可以达到我们想要的效果了

cout<<"子类的数据"<

cout<<"父类的数据"<

这样就ok了啊

2)同名成员函数处理

函数处理其实和成员变量处理方式一样,加个作用域就可以

son s1;

s1.func();//子类函数调用

s1.base::func();//父类函数调用

但是这里要介绍一个容易出现问题的地方:

class base

{

public:

base()

{

m_a=100;

}

void func()

{

cout<<"父类的函数调用"<

}

void func(int a)

{

cout<<"父类的函数调用(int a)"<

}

int m_a;

};

class son:public base

{

public:

son()

{

m_a=200;

}

void func()

{

cout<<"子类的函数调用"<

}

int m_a;

};

void test_01()

{

son s1;

s1.func(100);

}

在父类里面我们对func()函数进行了一个有参重载

但是在调用s1.func(100)会出现报错

为什么加了参数还不能定位到父类函数呢?——其实原因就在于子类创建后,会屏蔽一切所有父类同名函数,切记是同名,所以解决方法,再加一个作用域就好啦

son s1;

s1.base::func(100);

小总结

子类可以直接访问,子类中同名成员子类访问父类同名成员,需加上作用域

4.继承同名静态成员处理方法

1)通过对象访问

就是简单的添加作用域访问

#include

using namespace std;

class base

{

public:

static int m_a;

};

int base:: m_a=100;

class son:public base

{

public:

static int m_a;

};

int son:: m_a=200;

void test_01()

{

son s1;

cout<

cout<

}

int main()

{

test_01();

return 0;

}

2)通过类名访问

void test_01()

{

//通过类名访问

cout<

cout<

//通过 son 继承的 base 路径访问

cout<

}

这就是static特殊的地方,创建了就一直存在,所有在作用域内的代码可以访问同一块地址

小总结

主要就是static可以用类访问,但切记变量类内声明,类外初始化函数同样的方法可以访问,函数可在直接类内定义

5.菱形继承

如下图所示,在B,C继承A之后,我们D多继承B,C之后,那么我们对于m_a该如何访问并修改呢?

首先如下代码所示:

#include

using namespace std;

class A

{

public:

int m_a;

};

class B:public A

{};

class C:public A

{};

class D:public B,public C

{};

void test_01()

{

D d1;

d1.B::m_a=100;

d1.C::m_a=300;

cout<<"B的a:"<

cout<<"C的a:"<

}

int main()

{

test_01();

return 0;

}

输出结果如下:

这里其实和第三节方法是一样的,是对同名变量的操作

但是,这里其实是有问题,这样两个变量都是对A的继承,就会造成资源浪费,那我们怎么解决呢?

这里就引出一个新的概念——虚继承

class B:virtual public A

{};

class C:virtual public A

{};

我们只需将B,C加上virtual,就可以解决问题

这时候的完整代码:

#include

using namespace std;

class A

{

public:

int m_a;

};

class B:virtual public A

{};

class C:virtual public A

{};

class D:public B,public C

{};

void test_01()

{

D d1;

d1.B::m_a=100;

d1.C::m_a=300;

cout<<"B的a:"<

cout<<"C的a:"<

}

int main()

{

test_01();

return 0;

}

输出结果如下所示:

可以发现,这时候m_a已经是一个变量了,不会造成出现两个这种情况了

6.总结

这就是我对继承的理解啦!从语法到实际使用,其实并不难,只要多写几次自然就熟悉了。下一篇我会记录下“多态”的使用,尤其是虚函数和虚继承的细节,欢迎继续关注!

相关推荐

考虫英语四级有用吗(考虫四六级英语怎么样)
Bet体育365提款流程

考虫英语四级有用吗(考虫四六级英语怎么样)

📅 08-23 👁️ 850
五年了,晶方科技,这次真爆了!
Bet体育365提款流程

五年了,晶方科技,这次真爆了!

📅 09-14 👁️ 1639
常州武进竺山湖小镇附近停车场攻略、停哪里最方便
365beat怎么下载苹果

常州武进竺山湖小镇附近停车场攻略、停哪里最方便

📅 10-18 👁️ 282