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
相关文章
|
25天前
|
编译器 C++ 开发者
【C++】继承
C++中的继承是面向对象编程的核心特性之一,允许派生类继承基类的属性和方法,实现代码复用和类的层次结构。继承有三种类型:公有、私有和受保护继承,每种类型决定了派生类如何访问基类成员。此外,继承还涉及构造函数、析构函数、拷贝构造函数和赋值运算符的调用规则,以及解决多继承带来的二义性和数据冗余问题的虚拟继承。在设计类时,应谨慎选择继承和组合,以降低耦合度并提高代码的可维护性。
32 1
【C++】继承
|
2月前
|
安全 程序员 编译器
【C++篇】继承之韵:解构编程奥义,领略面向对象的至高法则
【C++篇】继承之韵:解构编程奥义,领略面向对象的至高法则
90 11
|
2月前
|
C++
C++番外篇——对于继承中子类与父类对象同时定义其析构顺序的探究
C++番外篇——对于继承中子类与父类对象同时定义其析构顺序的探究
61 1
|
2月前
|
C++
C++番外篇——虚拟继承解决数据冗余和二义性的原理
C++番外篇——虚拟继承解决数据冗余和二义性的原理
45 1
|
2月前
|
安全 编译器 程序员
C++的忠实粉丝-继承的热情(1)
C++的忠实粉丝-继承的热情(1)
21 0
|
2月前
|
编译器 C++
C++入门11——详解C++继承(菱形继承与虚拟继承)-2
C++入门11——详解C++继承(菱形继承与虚拟继承)-2
39 0
|
2月前
|
程序员 C++
C++入门11——详解C++继承(菱形继承与虚拟继承)-1
C++入门11——详解C++继承(菱形继承与虚拟继承)-1
41 0
|
3月前
|
C++
C++(二十)继承
本文介绍了C++中的继承特性,包括公有、保护和私有继承,并解释了虚继承的作用。通过示例展示了派生类如何从基类继承属性和方法,并保持自身的独特性。此外,还详细说明了派生类构造函数的语法格式及构造顺序,提供了具体的代码示例帮助理解。
|
3月前
|
C++
c++继承层次结构实践
这篇文章通过多个示例代码,讲解了C++中继承层次结构的实践应用,包括多态、抽象类引用、基类调用派生类函数,以及基类指针引用派生类对象的情况,并提供了相关的参考链接。
|
4月前
|
安全 Java 编译器