c++继承的相关知识点

简介: c++继承的相关知识点

继承的基础语法


当我们写类的时候,如果每个类都有相同的部分,那么通过一个个将其中的内容一个个敲出来将会十分占空间,那么我们就会用到继承


方法:将公共的内容专门写出一个类出来,然后写别的子类时候,加入公共部分即可。

语法:class 子类:继承方式 父类

(其中子类又叫做派生类,父类叫做基类)


下面看例子:


#include <iostream>
#include <string>
using namespace std;
//这里是公共的部分,也就是下面子类都共有的部分,先写出来
class BasePage
{
public:
  void head()
  {
  cout<<"上部的内容:........"<<endl;
  }
  void foot()
  {
  cout<<"下部的内容:........"<<endl;
  }
  void left()
  {
  cout<<"左边的内容:........"<<endl;
  }
};
//子类c++
class Cpp:public BasePage  //这里就可以将公共的部分添加至类中,减少重复内容
{
public:
  void cpp1()
  {
  cout<<"c++的内容"<<endl;
  }
};
class Py:public BasePage  //这里同样也是
{
public:
  void py1()
  {
  cout<<"python的内容"<<endl;
  }
};
void test()
{
  //分别输出对应的自己有的内容和公共的内容
  Cpp c;
  c.head();
  c.foot();
  c.left();
  c.cpp1();
  cout<<"---------"<<endl;
  Py py;
  py.foot();
  py.head();
  py.left();
  py.py1();
}
int main()
{
  test();
  system("pause");
  return 0;
}


运行程序:



好处:可以减少很多在子类中重复的内容

———————————————————————————————————

继承方式

公共继承 保护继承 私有继承

若子类公共继承父类,那么除了父类的私有属性访问不到其余与父类对应继承

若子类保护继承父类,那么除了父类的私有属性访问不到其余都为保护继承

若子类私有继承父类,那么除了父类的私有属性访问不到其余都为私有继承


注意在类外,对于类的保护属性以及私有属性都不能访问及修改,公共属性可以访问及修改


例子:


#include <iostream>
#include <string>
using namespace std;
class father
{
public:  
  int a;
protected:
  int b;
private:
  int c;
};
//公共继承
class son1:public father
{
public:
  void func()
  {
  a = 100;  //此时a为公共继承
  b = 100;  //b为保护继承
  //c = 100;  //c访问不到
  }
};
void test01()
{
  son1 s;
  s.a = 100;   //是公共属性可以访问到
  //s.b =200;  //类外访问不到保护属性
}
//保护继承
class son2:protected father
{
public:
  void func()
  {
  a = 100;  //此时a为保护继承
  b = 100;  //b为保护继承
  //c = 100;  //c访问不到
  }
};
void test02()
{
  son2 s;
  //s.a = 100;  //类外访问不到a
  //s.b =200; //类外访问不到b
}
//私有继承
class son3:private father
{
public:
  void func()
  {
  a = 100;  //此时a为保护继承
  b = 100;  //b为保护继承
  //c = 100;  //c访问不到
  }
};
void test03()
{
  son3 s;
  //s.a = 100;  //类外访问不到a,因为是私有属性
  //s.b =200; //类外访问不到b,因为是私有属性
}
int main()
{
  test01();
  system("pause");
  return 0;
}



———————————————————————————————————

父类中的所有非静态成员属性都会被子类继承下去

父类中私有成员属性也会被继承下去,只不过是被编译器隐藏了


子类继承父类时,构造函数与析构函数的顺序?

答:当子类继承父类的时候,先调用父类构造函数,再调用子类构造函数,析构函数与其相反


———————————————————————————————————

继承同名的成员关系

1.子类对象可以直接访问到子类中同名成员

2.子类对象加作用域可以访问到父类同名成员

3.当子类与父类拥有同名的成员函数,子类会隐藏掉父类中同名的成员函数,加作用域可以访问到父类的成员函数

例子:


#include <iostream>
#include <string>
using namespace std;
//父类
class father
{
public:
  father()
  {
  a = 100;
  }
  void func()
  {
  cout<<"父类进行调用"<<endl;
  }
  void func(int a)
  {
  cout<<"a = "<<a<<endl;
  }
  int a;
};
//子类进行公共继承父类
class son:public father
{
public:
  son()
  {
  a = 200;
  }
  void func()
  {
  cout<<"子类进行调用"<<endl;
  }
  int a;
};
//子类父类同名成员属性时候
void test()
{
  son s1;
  cout<<"son中的a:"<<s1.a<<endl;  //直接访问,就可以访问到子类的成员属性
  cout<<"father中的a:"<<s1.father::a<<endl; //加一个作用域就可以访问到父类的成员属性
}
//同名成员函数
void test01()
{
  son s1;
  s1.func();//直接进行调用子类中的同名函数
  //当父类与子类拥有同样名字的成员函数,编译器会自动隐藏掉父类的成员函数,
  s1.father::func(100);  //加上作用域才能访问父类的成员函数,不能直接调用s1.func(100)
}
int main()
{
  test01();
  system("pause");
  return 0;
}


———————————————————————————————————

访问同名静态成员,与非静态相似

例子:


#include <iostream>
#include <string>
using namespace std;
//定义一个父类
class Base
{
public:
  static void func()
  {
  cout<<"父类的void func()进行调用"<<endl;
  }
  static void func(int a)
  {
  cout<<"父类的static void func(int a)调用"<<endl;
  }
  static int a;
};
int Base::a = 100;
//定义一个子类
class son:public Base
{
public:
  //静态成员函数
  static void func()
  {
  cout<<"子类的void func()进行调用"<<endl;
  }
  static int a;  //类内静态变量初始化
};
int son::a = 200;
//访问静态成员属性
void test01()
{
  //1.通过对象访问静态成员属性
  cout<<"通过对象访问静态成员函数"<<endl;
  son s1; 
  cout<<"son下的静态成员属性"<<s1.a<<endl;      //直接访问类内成员
  cout<<"Base下的静态成员属性"<<s1.Base::a<<endl; //访问子类时要加作用域
  //2.通过类名来访问
  cout<<"通过类名访问静态成员函数"<<endl;
  cout<<"son下的静态成员属性"<<son::a<<endl;      //直接访问类内成员
  cout<<"Base下的静态成员属性"<<Base::a<<endl;  //访问子类时要加作用域
}
//访问静态成员函数
void test02()
{
  //通过对象访问
  cout<<"通过对象访问"<<endl;
  son s1;
  //s1.func(100);  //若子类成员函数与父类相同时,会隐藏父类的同名成员函数,需要加作用域才能访问
  s1.Base::func(100);
  s1.func();
  s1.Base::func();
  //2.通过类名访问
  cout<<"通过类名访问"<<endl;
  son::func();
  Base::func();
}
int main()
{
  test02();
  system("pause");
  return 0;
}



———————————————————————————————————

多继承语法:class 子类:继承方式 父类1,继承方式 父类2 {};

例子:


#include <iostream>
#include <string>
using namespace std;
class Base1  //父类1
{
public:
  Base1()
  {
  m_a = 100;  //设一个同名m_a
  }
  int m_a;
};
class Base2 //父类2
{
public:
  Base2()
  {
  m_a = 200;
  }
  int m_a;
};
class son:public Base1,public Base2  //继承两个父类
{
public:
  son()
  {
  m_a = 400;
  d = 300;
  }
  int m_a;
  int d;
};
void test()
{
  son s;
  cout<<"sizeof(s):"<<sizeof(s)<<endl;
  cout<<"子类下的m_a = "<<s.m_a<<endl;   //直接访问
  cout<<"Base1下的m_a = "<<s.Base1::m_a<<endl; //加作用域
  cout<<"Base2下的m_a = "<<s.Base2::m_a<<endl; //加作用域
  //总结:多继承下访问父类继承下来同名要加作用域
}
int main()
{
  test();
  system("pause");
  return 0;
}


总结:多继承下访问父类继承下来同名要加作用域


———————————————————————————————————

菱形继承

形成条件:

1.两个派生类继承一个基类

2.一个类再继承两个派生类

这个就叫做菱形继承,也叫做钻石继承


问题:此时这个类便产生了两义性


解决:

1.在继承之前加virtual,此时父类又称为虚基类

2.此时可以直接访问这个类的成员属性


例子:


#include <iostream>
#include <string>
using namespace std;
class animal
{
public:
  int m_age;
};
class sheep:virtual public animal {};  //下面两个派生类继承一个基类
class tuo:virtual public animal {};
class sheeptuo:public sheep,public tuo {};//一个类再继承两个派生类,此时便有了二义性,有两个m_age
void test01()
{
  sheeptuo st;
  st.sheep::m_age = 18;
  st.tuo::m_age = 15;  //哪个最后更改数值,就为哪个,并且两个继承类的属性都会更改
  cout<<"羊的年龄为:"<<st.sheep::m_age<<endl;
  cout<<"驼的年龄为:"<<st.tuo::m_age<<endl;
  cout<<"羊驼的年龄为:"<<st.m_age<<endl;    //继承之前加上virtual 便可以直接进行访问
}
int main()
{
  test01();
  system("pause");
  return 0;
}



运行程序:三个年龄都为15,是按照最后赋值的结果来进行指向的。


时间:2020.1.14-15
相关文章
|
2月前
|
安全 Java 编译器
C++进阶(1)——继承
本文系统讲解C++继承机制,涵盖继承定义、访问限定符、派生类默认成员函数、菱形虚拟继承原理及组合与继承对比,深入剖析其在代码复用与面向对象设计中的应用。
|
6月前
|
存储 安全 Java
c++--继承
c++作为面向对象的语言三大特点其中之一就是继承,那么继承到底有何奥妙呢?继承(inheritance)机制是面向对象程序设计使代码可以复用的最重要的手段,它允许程序员在保持原有类特性的基础上进行扩展,增加功能,这样产生新的类,称派生类。继承呈现了面向对象程序设计的层次结构,体现了由简单到复杂的认知过程。以前我们接触的复用都是函数复用,继承是类设计层次的复用,继承就是类方法的复用。
151 0
|
9月前
|
安全 C++
【c++】继承(继承的定义格式、赋值兼容转换、多继承、派生类默认成员函数规则、继承与友元、继承与静态成员)
本文深入探讨了C++中的继承机制,作为面向对象编程(OOP)的核心特性之一。继承通过允许派生类扩展基类的属性和方法,极大促进了代码复用,增强了代码的可维护性和可扩展性。文章详细介绍了继承的基本概念、定义格式、继承方式(public、protected、private)、赋值兼容转换、作用域问题、默认成员函数规则、继承与友元、静态成员、多继承及菱形继承问题,并对比了继承与组合的优缺点。最后总结指出,虽然继承提高了代码灵活性和复用率,但也带来了耦合度高的问题,建议在“has-a”和“is-a”关系同时存在时优先使用组合。
488 6
|
11月前
|
C++ 开发者
C++学习之继承
通过继承,C++可以实现代码重用、扩展类的功能并支持多态性。理解继承的类型、重写与重载、多重继承及其相关问题,对于掌握C++面向对象编程至关重要。希望本文能为您的C++学习和开发提供实用的指导。
169 16
|
11月前
|
编译器 数据安全/隐私保护 C++
【C++面向对象——继承与派生】派生类的应用(头歌实践教学平台习题)【合集】
本实验旨在学习类的继承关系、不同继承方式下的访问控制及利用虚基类解决二义性问题。主要内容包括: 1. **类的继承关系基础概念**:介绍继承的定义及声明派生类的语法。 2. **不同继承方式下对基类成员的访问控制**:详细说明`public`、`private`和`protected`继承方式对基类成员的访问权限影响。 3. **利用虚基类解决二义性问题**:解释多继承中可能出现的二义性及其解决方案——虚基类。 实验任务要求从`people`类派生出`student`、`teacher`、`graduate`和`TA`类,添加特定属性并测试这些类的功能。最终通过创建教师和助教实例,验证代码
353 5
|
编译器 C++ 开发者
【C++】继承
C++中的继承是面向对象编程的核心特性之一,允许派生类继承基类的属性和方法,实现代码复用和类的层次结构。继承有三种类型:公有、私有和受保护继承,每种类型决定了派生类如何访问基类成员。此外,继承还涉及构造函数、析构函数、拷贝构造函数和赋值运算符的调用规则,以及解决多继承带来的二义性和数据冗余问题的虚拟继承。在设计类时,应谨慎选择继承和组合,以降低耦合度并提高代码的可维护性。
244 1
【C++】继承
|
C++
C++番外篇——对于继承中子类与父类对象同时定义其析构顺序的探究
C++番外篇——对于继承中子类与父类对象同时定义其析构顺序的探究
164 1
|
C++
C++番外篇——虚拟继承解决数据冗余和二义性的原理
C++番外篇——虚拟继承解决数据冗余和二义性的原理
155 1
|
安全 编译器 程序员
C++的忠实粉丝-继承的热情(1)
C++的忠实粉丝-继承的热情(1)
|
编译器 C++
C++入门11——详解C++继承(菱形继承与虚拟继承)-2
C++入门11——详解C++继承(菱形继承与虚拟继承)-2
192 0