C++继承与派生

Wesley13
• 阅读 720

继承与派生

说明:以下实验证明一个是出自以Person类为父类,Student为子类的源代码,另一个出自以Point为父类,Recetangle为子类的源代码

派生类生成过程

1.吸收基类成员
2.改造基类成员
3.添加新成员

过程三步骤详述

  • 吸收基类成员
    派生过程中构造函数和析构函数都不被继承,因此在对派生类新增成员进行初始化,需要在派生类写构造函数负责对新增成员的初始化,而从基类继承的成员,依旧由基类的构造函数完成

  • 改造基类成员
    (1)基类成员的访问问题,靠继承方式控制
    (2)对基类数据或函数成员的覆盖和隐藏,如果派生类声明了一个和某个基类成员同名的新成员(注:函数要参数相同,如果不同的话,就是函数重载),派生的新成员会隐藏基类中同名的函数,并且在类外通过生成对象来直接使用成员名时,基类的成员就会被隐藏,即同名隐藏

同名隐藏
C++继承与派生 C++继承与派生

同名隐藏前:
C++继承与派生

同名隐藏后:
C++继承与派生

  • 添加新成员
    通过派生类中新成员派生类新功能的实现:

Person类中的成员函数:
C++继承与派生

Student类中的成员函数:
C++继承与派生

访问控制

  • 继承语法:
    Class 派生类名:继承方式(public private protected) 基类名{}
  • 分类:
    (1)公有继承:(常用)
    当类的继承方式是公有继承,即public时,父类中public和protected中的成员访问属性不变,而父类private中的成员在子类中不能直接访问,可通过从父类中继承的公共接口对此进行操作

私有成员报错
C++继承与派生

公有和保护成员不报错
C++继承与派生

(2)私有继承:(不常用)
当类的继承方式是私有继承,即private时,父类的公有成员和保护成员以私有成员的身份出现在子类中,在子类内部可以互相互访问,但在类外通过对象就不能访问和操作,而父类private中的成员在子类中还是子类外都不能直接访问经过私有继承后,父类中的成员成为子类私有成员或者不可直接访问的成员,那么如果进一步派生的话,基类的全部成员就无法在新的派生类中直接访问

子类内部不报错
C++继承与派生

通过对象访问报错
C++继承与派生

(3)保护继承:
当类的继承方式是保护继承,即protected时,父类的公有成员和保护成员以保护成员的身份出现在子类中,在子类内部可以互相访问,但在类外通过对象就不能访问和操作,而父类private中的成员在子类中还是子类外都不能直接访问

子类内部不报错
C++继承与派生

通过对象访问报错
C++继承与派生

以上所有实验的代码

以Point类为父类,Recetangle为子类的源代码

头文件声明:

#ifndef POINT_H
#define POINT_H

//Point类定义

class Point
{
public:
    void initP(float xx , float yy ) ;
    void move(float xoff, float yoff);
    float getX() const;
    float getY() const;
private:
    float x, y;
};

//retangle类定义
class Recetangle:private Point
{
public:
    void initR(float x, float y, float w, float h);
    float getWidth() const;
    float getHeight() const;
private:
    float w, h;
};

头文件函数实现:

#include "point.h"
#include<iostream>

using namespace std;

//point类函数实现
 void Point::initP(float xx=0, float yy = 0) 
{
    x=xx;
    y=yy;
}
void Point::move(float xoff, float yoff)
{
    x += xoff;
    y += yoff;
}
float Point::getX() const
{
    return x;
}
float Point::getY() const
{
    return y;
}


//Recetangle类函数实现
 void Recetangle::initR(float x, float y, float w, float h)
{
    initP(x, y);//私有继承,公有成员子类内部可以访问
    this->w = w;
    this->h = h;
}
float Recetangle::getHeight() const
{
    return h;
}
float Recetangle::getWidth() const
{
    return w;
}

main函数:

#include"point.h"
#include <iostream>

using namespace std;

int main()
{
    /*Recetangle test;
    test.initR(2, 3, 20, 30);
    test.move(3, 2);
    cout << test.getX() << "  "
        << test.getY ()<< "  "
        << test.getWidth() << "  "
        <<test.getHeight() << "  "
        << endl;*/

    //Recetangle test2;
    //test2.getX();//以私有继承,在类外通过对象进行访问,编译器报错
    //test2.getY();

    //Recetangle test3;
    //test3.getX();
    //test3.initP();//以保护继承,在类外不能通过对象访问
            
    return 0;
}

以Person类为父类,Student为子类的源代码

头文件声明:

#ifndef PCH_H
#define PCH_H

#include<string>

using namespace std;

class Person
{
public:
    Person();
    ~Person();
    void Inputinfo();
    void Showinfo() const;
private:
    string name;
protected:
    int age;
    
};
class Student:public Person
{
public:
    Student();
    void Inputinfo2();
    //void Inputinfo();//同名隐藏实验
    void Showinfo2() const;

private:
    float  grades;
    int id;
};

头文件中函数实现:

#include "pch.h"
#include<iostream>
#include<string>

using namespace std;


/****Person类成员函数实现****/

//功能:构造函数
Person::Person():name(name),age(age){}

//功能:析构函数,人数减1
Person::~Person(){}

//功能:输入用户名字、年龄
void Person::Inputinfo()
{
    cout << "Pleasing input your name" << endl;
    cin >> name;
    cout << "Pleasing input your age" << endl;
    cin >> age;
}

//功能:显示用户名字、年龄
void Person::Showinfo() const
{
    cout << "用户名: " << name << " \t " << "年龄 :" << age;
    
}



/****Student类成员函数的实现****/

//功能:Student类中构造函数实现
Student::Student():id(id),grades(grades){}

//功能:输入学生名字、年龄、学号、成绩
void Student::Inputinfo2()
{
    Inputinfo();
    cout << "Pleasing input your id" << endl;
    cin >> id;
    cout << "Pleasing input your grades" << endl;
    cin >> grades;
}

////功能:输入学生学号、成绩(实现同名隐藏,通过对象操作时同名函数采取就近原则)
//void Student::Inputinfo()
//{
//    cout << "Pleasing input your id" << endl;
//    cin >> id;
//    cout << "Pleasing input your grades" << endl;
//    cin >> grades;
//}

//功能:显示学生名字、年龄、学号、成绩
void Student::Showinfo2() const
{
    Showinfo();
    cout << "\t";
    cout << "学号: " << id << " \t " << "成绩: " << grades << endl;
}

////测试子类不能直接访问父类私有成员,编译器报错
//void Student::Showinfo2() const
//{
//    cout << name
//        << age;
//}


////测试以public继承,父类的公有成员和保护成员在子类内部可以直接访问,编译器不报错
//void Student::Showinfo2() const
//{
//    Showinfo();//父类公有成员
//    cout << age;//在做这步实验时,将原本私有成员的age改成了保护成员
//    cout << "\t";
//    cout << "学号: " << id << " \t " << "成绩: " << grades << endl;
//}

main函数:

#include "pch.h"
#include <iostream>
#include<string>

using namespace std;


int main()
{
    /*Person p1;
    p1.Inputinfo();
    p1.Showinfo();*/

    Student stu1;
    //stu1.Inputinfo();//同名隐藏前,原本Person类中Inputinfo函数输入的是name和age
    stu1.Inputinfo2();
    stu1.Showinfo2();

    return 0;
}
点赞
收藏
评论区
推荐文章
Irene181 Irene181
3年前
一篇文章带你搞懂Python中的继承和多态
一、继承的介绍继承是一种创建新的类的方式,新创建的叫子类,继承的叫父类、超类、基类。继承的特点就是子类可以使用父类的属性(特征、技能)。继承是类与类之间的关系。继承可以减少代码冗余、提高重用性。在现实生活中,继承一般指的是子女继承父辈的财产,如下图:二、如何用继承?1.继承语法Class派生类名(基类名):基类名写在括号里。在继承关系中,已有的,设计好
Jacquelyn38 Jacquelyn38
3年前
你不可不知的JS面试题(第二期)
1、什么是继承?子类可以使用父类的所有功能,并且对功能进行扩展。新增方法改用方法(1)、ES6使用extends子类继承父类的方法。// 父类    class A        constructor(name)            this.name name;                getNa
Wesley13 Wesley13
3年前
java向上转型和向下转型1
  在java继承体系中,认为父类(超类)在上层,子类在下层(派生类),向上转型就是把子类对象转成父类对象。1publicclassFather{2publicvoideat(){3System.out.println("我是父类的方法吃。。。。。");4}
Java修道之路,问鼎巅峰,我辈代码修仙法力齐天
<center<fontcolor00FF7Fsize5face"黑体"代码尽头谁为峰,一见秃头道成空。</font<center<fontcolor00FF00size5face"黑体"编程修真路破折,一步一劫渡飞升。</font众所周知,编程修真有八大境界:1.Javase练气筑基2.数据库结丹3.web前端元婴4.Jav
Wesley13 Wesley13
3年前
java中经常问到的面试题
1、面向对象编程的三大特性是什么?(1).继承:继承是一种联结类的层次模型,并且允许和鼓励类的重用,它提供了一种明确表述共性的方法。对象的一个新类可以从现有的类中派生,这个过程称为类继承。新类继承了原始类的特性,新类称为原始类的派生类(子类),而原始类称为新类的基类(父类)。派生类可以从它的基类那里继承方法和实例
Stella981 Stella981
3年前
C++primer学习笔记(六)
1.virtual函数是基类希望派生类重新定义的函数,希望派生类继承的函数不能为虚函数。根类一般要定义虚析构函数。2.派生类只能通过派生类对象访问protected成员,不能用基类对象访问。基类定义为virtual就一直为虚函数,派生类写不写virtual都是虚函数。用做基类的类必须是已定义的。3.存在虚函数指针或引用
Stella981 Stella981
3年前
Python Day24:类的继承、派生、覆盖、super()、绑定、非绑定方法
类的继承、派生、覆盖、super()python类的继承:子类继承父类,只需要在定义类的时候在类名后面加上(父类名)。继承之后,父类的属性方法、子类都可以访问派生:子类继承父类后,自己在父类的基础上,又添加了一些属于自己特性的属性、方法
Wesley13 Wesley13
3年前
C++多态学习之向下强制类型转换
向下强制类型转换在C中,基类(父类)指针可以指向派生类(子类)对象,因为派生类对象也是一个基类对象(但反过来不一样,基类对象不是一个派生类对象)。然而基类指针只能调用基类的成员函数,如果试图使用该指针调用仅在派生类中含有的成员函数(子类特有的,不是继承和重写父类的函数),将会产生编译错误。为了避免这一错误,就必须将基类指针转换成为派
小万哥 小万哥
1年前
Python 继承和子类示例:从 Person 到 Student 的演示
继承允许我们定义一个类,该类继承另一个类的所有方法和属性。父类是被继承的类,也叫做基类。子类是从另一个类继承的类,也叫做派生类。创建一个父类任何类都可以成为父类,因此语法与创建任何其他类相同:示例,创建一个名为Person的类,具有firstname和la
小万哥 小万哥
10个月前
C# 继承、多态性、抽象和接口详解:从入门到精通
C继承在C中,可以将字段和方法从一个类继承到另一个类。我们将“继承概念”分为两类:派生类(子类)从另一个类继承的类基类(父类)被继承的类要从一个类继承,使用:符号。在以下示例中,Car类(子类)继承了Vehicle类(父类)的字段和方法:示例csharpc