new/delet 是C++编译器实现的关键字,以类型为单位分配,申请时可以初始化内存
malloc/free 是C库实现的函数,以字节为单位分配,并不会初始化内存
#include <iostream> #include <string> #include <cstdlib> using namespace std; class superclass { public: superclass() { cout << "superclass constructor" << endl; } virtual ~superclass() { cout << "superclass destructor" << endl; } }; class subclass : public superclass { }; int main() { subclass* p_sub = new subclass; // 会触发构造函数 subclass* p_sub_1 = (subclass *) mallloc(sizeof(subclass)); // 不会触发构造函数 subclass* p_sub_2 = dynamic_cast<subclass*>(p_sub); delete p_sub; // 会触发析构函数 free(p_sub_1); // 不会触发析构函数 return 0; }
构造函数不可能成为虚函数:在构造函数执行完后,虚函数表和虚函数表指针才会初始化。
析构函数可以成为虚函数:尽量将析构函数声明为虚函数。(当定义指向子类的父类指针后,再delete父类指针时,子类的析构函数函数也会被调用,避免了内存泄漏。尽量把析构函数声明为虚函数)
构造函数不可以发生多态行为:在构造函数之前,虚函数表指针还未初始化。
析构函数不可以发生多态行为:在析构函数之前,虚函数表指针就被销毁。
构造函数和析构函数:调用当前类定义的虚函数,并不会发生多态的行为
#include <iostream> #include <string> using namespace std; class superclass { public: superclass() // 不可以声明为虚函数 { func(); // 构造函数中调用虚函数,不会发生多态,运行本类中的虚函数 } virtual void func() { cout << "superclass virtual function" << endl; } virtual ~superclass() // 尽量将析构函数声明为虚函数,防止未被调用而造成内存泄漏 { func(); // 析构函数中调用虚函数,不会发生多态,运行本类中的虚函数 } }; class subclass : public surperclass { public: subclass() { func(); } virtual void func() { cout << "subclass virtual function" << endl; } ~subclass() { func(); } }; int main() { superclass* p_super = new subclass(); delete p_super;
// 如果superclass 的虚构函数没有声明为虚函数,编译器会根据p_super的类型(superclass)调用superclass的析构函数,不会调用subclass的析构函数 // 当superclass的虚函数声明为虚函数,编译器会根据p_super指向的对象(subclass)来先调用subclass的析构函,再调用superclass的析构函数。 return 0; }
继承中的强制类型转换:
dynamic_cast用于有直接或间接继承关系的类的指针或引用之间的强制转换。
dynamic_cast要求:相关类中必须有虚函数,
指针:转换成功-->得到目标类型的指针。转换失败-->得到空指针。
引用:转换成功-->得到目标类型的应用。转换失败-->得到异常操作信息。
#include <iostream> #include <string> using namespace std; class superclass { public: superclass() { cout << "superclass constructtor" << endl; } virtual ~superclass() // 为了使用 dynmaic_cast 而声明成虚函数 { cout << "superclass destructor" << endl; } }; class subclass : public superclass { }; int main() { superclass* p_super1 = new superclass; subclass* p_sub1 = dynamic_cast<subclass*>(p_super1); // 不能用子类的指针指向父类,dynmaic_cast返回空指针 superclass* p_super2 = new subclass; subclass* p_sub2 = dynamic_cast<subclass*>(p_super2); // 不能用父类指针初始化子类指针,通过 dynamic_cast返回正确地址 delete p; return 0; }