继承多态与虚函数及对类的理解

    B是A的子类,子类会继承父类的public方法,子类对象可以调用父类的public接口,但是子类和父类函数重名时,父类的方法会被子类覆盖(隐藏),子类调用和父类同名同参函数或者重载父类的函数后不可以直接调用父类函数,需要加A::fun()调用,父类的protect方法只在继承中有效,子类可以调用父类的protect方法,但是外部无法访问,所以在非继承关系中protect与private等同,private方法只能由类内部的方法调用,也可以由友元函数和类调用,其他对象都不可以访问类的private数据。

     父类对象指向子类时只能调用子类从父类继承到的一部分函数,不可以调用子类新增的函数,所以指针向上转化是安全的,向下转化有问题,dynamic_cast会返回一个空指针。多态是指父类对象可以指向并调用子类中和父类同名同参函数,通过虚函数来实现,父类中定义的虚函数在子类不定义也是虚函数。虚函数通过虚函数表实现,32位机器的编译器有虚函数的类会多出4个字节的虚函数指针,指向虚函数表中的第一个虚函数,当父类对象指向子类并调用虚函数的时候,便从子类的虚函数表中找出对应的同名同参函数。纯虚函数是如同virtual fun(){}=0的函数,存在纯虚函数的类称为抽象类(纯虚类),抽象类不可以建立实例对象,只能由子类重写其纯虚函数。举个例子就如动物类virtual eat(){}=0而狗类virtual eat(){cout<<"bone"<<endl;}一个抽象类可以定义多个虚函数,均通过指向不同的子类对象由子类对象实例化,若子类未实例化纯虚函数,则子类也为抽象类,等待孙子类来实例化纯虚函数,才可以建立对象。纯虚类和虚基类不同,虚基类仅仅出现在多重继承关系中,虚继承使多个派生类共用一份基类的成员(基类必须使用默认构造函数才可以虚继承),并消除菱形继承中的孙子类歧义,应尽量避免多重继承的使用。

    类是对象的抽象,对象是类的实例。一个空类中存在默认构造函数,默认析构函数,默认拷贝构造函数(浅拷贝),默认运算符重载“=”,默认取地址符&和const取地址符&,当使用const取址的时候,需要注意const在*之后是说指针不允许指向其他的对象,而const在*之前才是说不允许使用指向该类的指针改变该类的任何成员,而且只能调用类的const方法。还有一个需要注意的是new和malloc可以在堆中创建对象,但malloc只是库函数,而new是运算符,只有new可以创建类对象,因为new可以自动调用类的默认构造函数并创建类的实例而malloc不可以。在类的内部一旦发生在堆上使用malloc或者new申请空间的事件的时候,需要注意默认拷贝构造函数和默认重载运算符“=”可能导致指针悬空问题,可能导致两个对象同时指向堆中的一块空间,在析构的时候会导致重复析构。如果需要用,需要重写默认拷贝构造函数和“=”重载,为新对象在堆中申请相应的空间。深拷贝:

  1. Person(const Person &p)  
  2. {  
  3.     m_name = new char[strlen(p.m_name)+1];  
  4.     if (m_name != 0)  
  5.     {  
  6.         strcpy(m_name,p.m_name);  
  7.         m_age = p.m_age;  
  8.     }  
  9. }  
在传引用参数前加const主要是防止不小心修改原有数据,尽量在不会更改原有数据的所有情况下加const限定防止出错。
    对类的构造可以使用成员初值列
  1. class STU  
  2. {  
  3. public:  
  4.     STU(string _name,string _sex,int _age):name(_name)  
  5.     {  
  6.         sex=_sex;  
  7.         age=_age;  
  8.     }  
  9.     void printStu()  
  10.     {  
  11.         cout<<"姓名:"<<name<<endl<<"性别:"<<sex<<endl<<"年龄:"<<age<<endl;  
  12.     }  
  13. private:  
  14.     string name;  
  15.     string sex;  
  16.     int age;  
  17. };  
当构造子类的时候,构造顺序应该是先父类,然后构造子类里的对象,然后构造子类自身。若父类或子类中的对象存在自定义的含参构造函数,必须先构造他们才能构造子类。
        在继承关系中,要将父类的析构函数声明为虚函数,防止父类指针指向子类的时候,无法析构子类而只析构父类。
#include <iostream>
using  namespace  std;
 
 
class  Person{
public :
     ~Person(){   //declare destructor as a virtual function
     cout <<  "Person::~Person()"  << endl;
     }
};
 
class  Student :  public  Person{
public :
     ~Student(){      // virtual or not is OK
         cout <<  "Student::~Student()"  << endl;
     }
};
 
int  main(){
     Person *pt1 =  new  Person;
     Person *pt2 =  new  Student;         // base class pointer point to derived class
     // Student *pt3 = new Person;     // derived class pointer can not point to base class
     Student *pt4 =  new  Student;
 
     delete  pt1;
     cout <<  "*********"  << endl;
     delete  pt2;
     cout <<  "*********"  << endl;
     //delete pt3;
     //cout << "*********" << endl;
     delete  pt4;
     cout <<  "*********"  << endl;
 
     return  0;
}

运行结果:

设计一个不能继承的类:
  1. #include<iostream>
  2.   using namespace std;
  3.   template <typename T> 
  4.   class Base
  5.   {
  6.   friend T;
  7.   private:
  8.   Base() {}
  9.   ~Base() {}
  10.  };
  11.  
  12.  class Finalclass : virtual public Base<Finalclass>
  13.  { 
  14.  public:
  15.  Finalclass() {}
  16.  ~Finalclass() {}
  17.  };
  18.  void main()
  19.  {
  20.  Finalclass *= new Finalclass; //堆上对象
  21.  Finalclass fs; //栈上对象
  22.  }



评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值