基类指针释放派生类对象方法

原因:基类对象的指针操作派生类对象时,防止析构函数只调用基类的,而不调用派生类的

 

下面详细说明:

 

//基类
 
class A{
   public :
       A(){ cout<<"A构造函数"<<endl; }
       ~A(){cout<<"A被销毁了"<<endl;}
       void Do(){
           cout<<"A要做点什么"<<endl;
       }
};
//派生类
 
class B :public A{
    public :
        B(){ cout<<"B构造函数"<<endl;}
        ~B(){ cout<<"B被销毁了"<<endl;}
        void Do(){ cout<<"B要做点什么"<<endl;}
};

 

(1)派生类 指针=new 派生类;

         B      *p   =new B;      那么就会执行基类构造函数,派生类构造函数

         p->Do();   通过派生类指针可以调用派生类的成员函数

         delete p;     先调用派生类析构函数,在调用基类构造函数

         

 派生类指针操作派生类成员函数

 

(2)派生类 指针=new 基类;  会出错,基类指针不能转换成派生类指针

 

(3)基类 指针 = new 派生类;  (派生类指针转化成基类指针)

       A    *p    = new B;     依旧要先调用基类构造函数,再派生类构造函数

       p ->Do();    通过基类指针调用基类成员函数,此处只能调用基类里面有的成员函数,当调用派生类中成员函数会提示基类中并没有这个成员

       delete p;      这里只会调用基类的析构函数,所以内存释放并不完全

 派生类指针转换成基类指针

 

   

(4)上面(3)知道了这样影响了内存的释放完整程度,所以我们通过引入虚函数机制,将基类的析构函数定义成虚函数

 

//基类
 
class A{
   public :
       A(){ cout<<"A构造函数"<<endl; }
       virtual ~A(){cout<<"A被销毁了"<<endl;}
       void Do(){
           cout<<"A要做点什么"<<endl;
       }
};
//派生类
 
class B :public A{
    public :
        B(){ cout<<"B构造函数"<<endl;}
        ~B(){ cout<<"B被销毁了"<<endl;}
        void Do(){ cout<<"B要做点什么"<<endl;}
};

 

然后 delete p;就会释放派生类,释放基类

 析构函数变成了虚函数,发现可以正常释放内存

 

 

总结:引入虚函数后,因为基类对象的指针可以指向派生类的对象(多态性),所以如果删除指针delete p,那么就会调用派生类得析构函数,但是派生类的析构函数就会调用基类的析构函数,这样整个派生类的对象完全被释放。但是如果不被声明成虚函数,那么删除指针时,只会调用基类的析构函数,而不会调用派生类的析构函数,这样释放对象就只释放不完全,所以把析构函数定义成虚函数是十分必要的。

 

还有派生类指针转换成基类指针的时候,调用同名成员函数的时候,一定要调用基类的成员函数,因为此时基类的成员函数覆盖了派生类的同名成员函数。这时也需要引入虚函数来实现多态,就可以调用派生类的成员函数了

好的,下面是代码实现: ```cpp #include <iostream> #include <string> using namespace std; class Role { protected: string name; int age; char gender; public: Role() { } Role(string n, int a, char g) : name(n), age(a), gender(g) { } void setName(string n) { name = n; } void setAge(int a) { age = a; } void setGender(char g) { gender = g; } string getName() { return name; } int getAge() { return age; } char getGender() { return gender; } virtual void display() { cout << "Name: " << name << endl; cout << "Age: " << age << endl; cout << "Gender: " << gender << endl; } }; class Employee : public Role { private: int ID; double salary; public: Employee() { } Employee(string n, int a, char g, int i, double s) : Role(n, a, g), ID(i), salary(s) { } Employee(string n, int a, char g) : Role(n, a, g) { } void setID(int i) { ID = i; } void setSalary(double s) { salary = s; } int getID() { return ID; } double getSalary() { return salary; } void display() { Role::display(); cout << "ID: " << ID << endl; cout << "Salary: " << salary << endl; } }; int main() { Role* r = new Employee("Tom", 30, 'M', 1001, 5000.0); r->display(); delete r; return 0; } ``` 输出结果: ``` Name: Tom Age: 30 Gender: M ID: 1001 Salary: 5000 ``` 在这个示例中,我们定义了一个基类 Role 和一个派生类 Employee。Employee 类继承了 Role 的所有成员,同时扩展了 ID 和 salary 两个成员。基类 Role 和派生类 Employee 都有两个构造函数,其中 Employee 重载了基类的构造函数,并在其中调用了基类的构造函数以初始化基类的成员。在 Employee 类中,我们也重新定义了 display() 函数,以便它能显示出 Employee 类的数据成员。在 main() 函数中,我们定义了一个基类指针 r,使它指向一个 Employee 对象。当我们调用 r->display() 时,它将调用 Employee 类中的 display() 函数,因为它是虚函数。注意,在 delete r 之后,我们需要释放动态分配的内存。
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值