C++笔记------类的继承和多态

从已有的类派生出新的类,叫继承。派生类继承了基类的特征和方法。
公有继承:基类的公有成员成为派生类的公有成员;基类的私有成员成为派生类的一部分,但只能经过基类成员方法和保护方法访问。
派生类构造函数,经过成员初始化列表的方式指明使用的基类构造函数,并传递基类信息。非构造函数不能使用初始化列表语法。数组

派生类可使用基类不是私有的方法。函数

class A { private: int num; public: int a; public: A():a(10),num(1) {} void Show_num() { cout << num <<endl; } ~A(){} }; class B:public A { public: int b; B():A(),b(5){} ~B(){} }; int main() { B b1; cout << b1.b <<" " << b1.a <<endl; b1.Show_num(); //b1只能经过基类公有方法访问私有数据。 }

在派生类的对象建立中,首先是虚基类的构造函数,并按照声明顺序构造。而后是非虚基类的构造函数,
以后是成员对象的构造函数,最后是派生类本身的构造函数。
派生类对象过时先调用派生类析构函数,而后再调用基类析构函数。spa

class D1 { public: D1() { cout << "D1 create" <<endl; } ~D1() { cout <<  "D1 free \n"; } }; class D2 { public: D2() { cout << "D2 create" <<endl; } ~D2() { cout <<  "D2 free \n"; } }; class D3 { public: D3() { cout << "D3 create" <<endl; } ~D3() { cout <<  "D3 free \n"; } }; class D4:public D1,virtual public D2 { public: D3 tt; D4():tt() { cout << "D4 create" <<endl; } ~D4() { cout <<  "D4 free \n"; } }; int main() { D4 tt; return 0; }

1.子类能给父类赋值(向上转换),但父类不能够给子类赋值指针

2.基类的指针能够指向派生类,基类的引用能够引用派生类对象。但只能调用基类的方法。派生类指针和引用不能够指向基类和引用基类。从新定义基类方法将隐藏基类方法。code

派生类可使用做用域解析符来调用基类方法。对象

class D1 { public: D1() { cout << "D1 create" <<endl; } void show() { cout << "D1 show"<< endl; }

      void show1()
      {
          cout <<" D1 show1()\n";
      }blog

      ~D1()继承

 { cout <<  "D1 free \n"; } }; class D2 { public: D2() { cout << "D2 create" <<endl; } void show() { cout << "D2 show" <<endl; } ~D2() { cout <<  "D2 free \n"; } }; class D4:public D1,virtual public D2 { public: D4():tt() { cout << "D4 create" <<endl; } void show() { cout << "D4 show" <<endl; }

      void show1(int i)
     {
          cout << i <<" D4 show1()\n";
     }作用域

~D4() { cout <<  "D4 free \n"; } }; int main() { D4 tt; D2 t2; D1 t1; t1 = tt; //tt = t1; //报错 
    D2* t3 = &tt; D1 & t4=tt; t3->show();      //调用D2的show函数
    t4.show();        //调用D1的show函数
    tt.show();        //调用D1的show函数
    tt.D1::show();  //调用D1的show函数
    //tt.show1();   //报错,显示没有show1()函数
tt.show1(2);
return 0; }

有两种多态性
  1.编译时的多态性,经过函数重载和运算符重载实现。
  2.运行时的多态,程序执行时没法根据函数名和参数肯定调用那一个函数,必须根据具体执行状况动态的肯定,经过类继承关系和虚函数实现。
Ps:原型

1.函数若是为虚函数则在继承体系中,函数一直默认为虚函数。

2.派生类中从新定义虚函数时(覆盖),要函数名,参数列表和返回值要与基类相同(三同)

3.若是返回类型是基类指针,派生类返回派生类指针是能够的。若是不一样则重载。

4.静态成员函数(全部对象共同拥有),内联函数,全局函数(只有类的成员函数才能是虚函数),不能做为虚函数。

5.构造函数不能定义为虚函数,由于调用构造函数是对象没有完成实例化。

6.若是函数在类内声明,类外实现。vistual只用在类声明的方法原型中。

7.使用virtual,程序根据引用或指针的对象选择方法。没有virtual,则根据引用或指针类型调用方法。

8.将基类的析构函数定义为虚析构函数,为了保护让程序正确调用析构函数。

9.编译器处理虚函数是为对象添加一个隐藏成员,该成员保存了指向虚函数的地址数组的指针,称为虚函数表。

重载,隐藏和覆盖

  重载:在同一做用域中,同名,不一样参数列表的函数之间是重载。
  隐藏:在父类中的函数没用virtual关键字,子类同名函数会隐藏父类函数,不能使用父类函数
  覆盖:在虚函数表中,子类的虚函数地址覆盖父类同名的虚函数地址

在多继承中虚函数表
  没有覆盖的状况下,子类的虚函数地址只会添加在第一个父类虚函数表后面,其它父类虚函数表中没有
  在有覆盖的状况下,子类的虚函数地址会覆盖全部父类同名的虚函数地址。

private与protected区别
  派生类成员能够直接访问基类保护成员,但不能直接访问基类私有成员。
  保护访问控制让派生类可以访问公众不能使用的内部函数。
纯虚函数

  virtual void show() = 0 ;

抽象基类(ABC):包含纯虚函数的类(不管有无实现),不能建立对象。

  由于纯虚函数没有实现部分,因此不能产生对象。

  子类若是没有重写ABC的纯虚函数则也不能建立对象,必须把全部纯虚函数重写。

  若是纯虚函数提供实现代码,能够经过类名作限定进行调用ABC的函数实现代码。

//有一个抽象基类A(已提供实现代码)
B b; b.show(); b.A::show();
相关文章
相关标签/搜索