C++学习笔记09--继承

面向对象编程之继承

    定义一个类的时候想重用一个已有的类,就可以使用继承。

      class NewClass:public OldClass{

        //新增加的成员

      };

    新类会继承旧类的全部成员,成为新类中的成员。新类可以增加新的成员,实现对旧类的扩展。继承方式可以有public/private/protected三种,一般使用public方式。旧类成为“父类”或者“基类”,新类称为“子类”或者“派生类”。无论哪种继承方式都是把父类的成员全部继承到子类中成为子类的成员,其中私有的成员在子类中不能直接访问,公开成员可以在子类中直接访问。特权是,父类中可以用protected来作为成员的访问限制,这种成员称为保护成员。这种成员对外跟private一样,但在子类中允许直接访问。×××尽量不用protected以免父子类之间有太强的耦合×××

    不同继承方式的区别在于继承到子类中之后作为子类的成员对外的访问限制

      private方式继承过来后所有的成员都成为子类的私有成员

      protected方式继承过来之后原来的私有还是私有,原来保护的和公开的都成为子类的保护成员

      public继承过来的成员到子类中之后保持原有的访问限制不变

      如果没写继承方式默认是private

      继承的主要作用是代码重用以及对多态提供支持。

#include<iostream>
using namespace std;
#include<string>

class Person{
protected://允许在子类中直接访问,不允许在别的地方访问
    string name;
public:
    void setname(const char* n){
    name=n;
    }
    void eat(string food){
        cout<<name<<"吃"<<food<<endl;
    }
    void speak(string words){
        cout<<name<<"说:|"<<words<<"|"<<endl;
    }
};
class Teacher:public Person{
    string course;
public:
    void teach(string someclass){
        cout<<this->name <<"给"<<someclass<<"讲"<<course<<"课"<<endl;
    }
    void setcourse(string c){course=c;}
};

int main()
{
    Person a;
    a.setname ("芙蓉");
    a.eat("水煮鱼");
    a.speak("我会跳舞");

    Teacher c;
    c.setname ("短哥");
    c.eat("杂酱面");
    c.speak("大家好!");
    c.setcourse ("C++");
    c.teach ("csd");
    system("pause");
}

    创建对象的顺序:分配内存,构造函数首先调用父类的构造函数,然后按照定义顺序创建成员对象,执行构造函数的函数体。析构跟构造相反。构造函数默认调用父类构造函数是不传参数,如果需要传递参数,要在初始化类表中用父类雷鸣来表示。×××初始化列表各项排名不分先后,只是指明用什么初始化谁×××

    子类定义的函数会隐藏来自父类的同名函数,即使参数表不同也不会构成重载。如果确实需要调用来自父类的那个函数,需要明确用“类名::”来指明。父子类之间不存在重载。

#include<iostream>
using namespace std;
#include<string>

class Person{
    string name;
public:
    const string& getName(){return name;}
    Person(const char* n):name(n){
        cout<<"Person("<<n<<")"<<endl;
    }
    ~Person(){
        cout<<"~Person"<<endl;
    }
    void show(){
        cout<<"大家好,我是"<<name<<endl;
    }
};

class Teacher: public Person{
    string course;
public:
    Teacher(const char* n,const char* c):course(c),Person(n){
        //Person(n);只是创建匿名对象,这个语句后立即释放
        cout<<"Teacher("<<n<<","<<c<<")"<<endl;
    }
    ~Teacher(){
        cout<<"~Teacher()"<<endl;
    }
    void show(const char* c){//隐藏来自父类的同名函数
        cout<<c<<"班的同学们好!我是"<<course<<"课程老师:"<<getName()<<"!"<<endl;
    }
};
int main()
{
    Person b("芙蓉");
    b.show();
    Teacher a("苍老师","C++");
    a.Person::show();//调用父类的show函数
    a.show("1");//调用子类的show函数
    system("pause");
}

     多重继承,一个类可以继承多个类,把所有父类的成员都全部继承过来,可以为每个父类制定一种继承方式。

      多个父亲的构造函数按继承顺序调用,与初始化列表中的顺序无关。析构顺序相反。

#include<iostream>
#include<string>
using namespace std;

class Phone{
public:
    Phone(){cout<<"Phone()"<<endl;}
    void Call(string Num){
        cout<<"打电话给:"<<Num<<endl;
    }
};

class Camera{
public:
    Camera(){cout<<"Camera()"<<endl;}
    void takephoto(string target){
        cout<<"照了一张"<<target<<"照。"<<endl;
    }
};

class CellPhone:public Phone,public Camera{
public:
    //按照继承顺序调用父类构造函数
    CellPhone(){cout<<"CellPhone()"<<endl;}
};

int main()
{
    CellPhone Nokia;
    Nokia.Call("芙蓉");
    Nokia.takephoto("风景");
    system("pause");
}

    虚继承

      如果希望某一个类被继承到某一级子类中时有了多份要合并只保留一份,这个类在被继承的时应该用virtual声明为虚继承,这个类就称为虚基类。

      虚继承(钻石继承)中虚基类的构造函数由最底下(合并)的子类的构造函数直接传递参数

      虚基类

     /      \

    子类1   子类2

      \    /

       子类

  

#include<iostream>
using namespace std;
#include <string>

class Person{
    string name;
public:
    Person(const char* n):name(n){
        cout<<"Person("<<n<<")"<<endl;
    }
    const string& Name()const{return name;}
};

class Teacher : virtual public Person{//virtual虚继承
    string course;
public:
    Teacher(const char* n,const char* c):course(c),Person(n){
        cout<<"Teacher("<<n<<","<<c<<")"<<endl;
    }
    void Teach(const char* c){
        cout<< Name()<<"老师在"<<c<<"班讲课"<<endl;
    }
};

class Student :virtual public Person{//virtual虚继承
    string sid;
public:
    Student(const char* n,const char* s):sid(s),Person(n){
        cout<<"Student("<<n<<","<<s<<")"<<endl;
    }
    void listen(const char* room){
        cout<<Name()<<"在"<<room<<"听课"<<endl;
    }
};

class DoubleMan : public Student,public Teacher{
public:
    DoubleMan(const char* n, const char* c,const char* id):Teacher(n,c),Student(n,id),Person(n){ //Person(n)虚基类的构造函数在这里直接传递
    cout<<"DoubleMan("<<n<<","<<c<<","<<id<<","<<")"<<endl;
    }
};

int main()
{
    DoubleMan dm("短哥","C++","X1110");
    dm.Teach("csd");
    dm.listen("508");
    cout<<"hello,"<<dm.Name()<<endl;
    system("pause");
    return 0;
}
时间: 2024-10-09 20:45:19

C++学习笔记09--继承的相关文章

C++学习笔记之继承

一.基类和派生类 很多时候,一个类的对象也“是”另一个类的对象,如矩形是四边形,在C++中,矩形类Rectangle可以由四边形类Quad继承而来,于是,四边形类Quad是基类,矩形类Rectangle是派生类.但是如果说四边形一定是矩形显然不对.几个简单的基类和派生类的例子: 基类                         派生类   食物 米饭.面条.水饺   交通工具 汽车.火车.飞机 国家 中国.美国.西班牙 可以看出,每个派生类的对象都是基类的一个对象,并且一个基类可以有很多派生

《机电传动控制》学习笔记09

<机电传动控制>学习笔记09 胡恒谦 机卓1301 1. 电力电子器件 电力电子器件根据其导通和关断可控性的不同可以分为以下三类. (1)不可控型器件,即导通与关断都不能控制的器件.仅整流二极管是不可控器件. (2)半控型器件,即只能控制其导通,不能控制其关断的器件.普通晶闸管SCR及其派生器件属于半控型器件. (3)全控型器件,即导通与关断都可以控制的器件.GTR.GTO.IGBT等都属于全控型器件. 2. 晶闸管 晶闸管导通条件为:加正向电压且门极有触发电流:其派生器件有:快速晶闸管,双向

Java学习笔记之继承

一.继承的基础 在Java术语中,被继承的类叫超类(superclass),继承超类的类叫子类(subclass). 举例说明: 1 class Box 2 { 3 public double width; 4 public double height; 5 public double depth; 6 7 //重载构造方法 8 public Box(Box ob) 9 { 10 width = ob.width; 11 height = ob.height; 12 depth = ob.dep

C++ GUI Qt4学习笔记09

C++ GUI Qt4学习笔记09 qtc++ 本章介绍Qt中的拖放 拖放是一个应用程序内或者多个应用程序之间传递信息的一种直观的现代操作方式.除了剪贴板提供支持外,通常它还提供数据移动和复制的功能. QMimeData是一个可以提供不同格式数据的类. 9.1使拖放生效 拖放操作有两个动作:拖动和放下.Qt窗口部件可以作为拖动点.放下点或者同时作为拖动点和放下点. 9.2支持自定义拖动类型 9.3剪贴板处理技术 多数应用程序都通过某一种或者几种方式来使用Qt的内置剪贴板处理技术. C++ GUI

C++ Primer Plus学习笔记之继承类的初始化顺序

C++ Primer Plus学习笔记之继承类的初始化顺序 基类的构造函数,析构函数和操作符函数operator=是不能被派生类继承的: 那么,当创建一个派生类对象时,怎样调用基类的构造函数对基类的数据进行初始化呢??? 答案是:构造函数执行时遵行先兄长(基类),再客人(对象成员),后自己(派生类)的顺序: 另一方面,执行析构函数时,先执行派生类的析构函数,再执行基类的析构函数.原因是,对基类的破坏隐含了对派生类的破坏,所以派生类的析构函数必须先执行: #include<iostream> u

C++学习笔记13-类继承

1.  类模板的 static 成员[不同于C#中的static] 类模板可以像任意其他类一样声明static 成员.以下代码: template <classT> class Foo { public: static std::size_tcount() { return ctr; } // other interfacemembers private: static std::size_tctr; // otherimplementation members }; 定义了名为Foo 的类模

CSS学习笔记09 简单理解BFC

1 <!DOCTYPE html> 2 <html lang="en"> 3 <head> 4 <meta charset="UTF-8"> 5 <title>BFC</title> 6 <style type="text/css"> 7 .div1 {background-color: #FCE38A; width: 200px; height: 100px;}

PHP学习笔记之继承(面向对象三大特性之一)

今天学习了面向对象的三大特性之一继承 继承:子类可以继承父类的一切 特点就是单继承: 制造一个父类 //继承:子类可以继承父类的一切//特点:单继承 //父类class Ren{ public $name; public $sex; public $yuyan; function Say() { echo $this->name."正在讲话!"; }} //美国人的子类class America extends Ren{ public $ziben; //子类对父类的方法重写 f

Codeigniter入门学习笔记09—路由

很久很久以前学习Codeigniter的笔记记录,很随意,但都是自己记录的,希望对需要的人有所帮助. 本文使用word2013编辑并发布 Postbird | There I am , in the world more exciting! Postbird personal website : http://www.ptbird.cn 路由 1.更改默认路由文件 ????application/config/routes.php ????默认控制器 ???? 2.伪静态 ????control

Objective-C学习笔记_继承、初始化方法、便利构造器

一.继承 继承的上层:父类,继承的下层:子类.继承是单向的,不能相互继承.继承具有传递性:A继承于B,B继承于C,A具有B和C的特征和?为.子类能继承父类全部的特征和行为. 例题 打僵尸.需求: 1.定义普通僵尸类: 实例变量:僵尸总血量.僵尸每次失血量. 方法:初始化方法(总血量).被打击失血.死亡. 2.定义路障僵尸类: 实例变量:僵尸总血量.僵尸每次失血量,道具,弱点. 方法:初始化方法(总血量).被打击失血.失去装备.死亡. 3.定义铁桶僵尸类: 实例变量:僵尸总血量.僵尸每次失血量,道