首页
学习
活动
专区
工具
TVP
发布
精选内容/技术社群/优惠产品,尽在小程序
立即前往

纯抽象基类上的虚拟析构函数

纯抽象基类上的虚拟析构函数是一种编程技巧,用于确保在使用多态性时,派生类的对象可以正确地被删除。在C++中,当一个类是纯抽象的(即它包含至少一个纯虚函数),它不能被实例化。因此,当我们使用多态性(如通过基类指针或引用)时,我们需要确保派生类的对象可以被正确地删除。为了实现这一点,我们需要在基类中声明一个虚拟析构函数。这样,当我们使用基类指针或引用删除派生类对象时,正确的析构函数将被调用。

例如,考虑以下代码:

代码语言:cpp
复制
class Base {
public:
    virtual ~Base() = 0;
};

Base::~Base() {
    // 析构函数实现
}

class Derived : public Base {
public:
    ~Derived() {
        // 派生类的析构函数实现
    }
};

int main() {
    Base* pBase = new Derived();
    delete pBase;
    return 0;
}

在这个例子中,我们声明了一个纯抽象基类Base,其中包含一个虚拟析构函数。当我们创建一个Derived类的对象并将其分配给Base类指针时,我们可以使用delete运算符来删除该对象。由于基类中的析构函数是虚拟的,因此Derived类的析构函数将被正确地调用,从而确保对象被正确地删除。

总之,在使用纯抽象基类时,我们需要在基类中声明一个虚拟析构函数,以确保派生类对象可以被正确地删除。这种技巧在实现多态性时非常有用,可以确保代码的可扩展性和可维护性。

页面内容是否对你有帮助?
有帮助
没帮助

相关·内容

抽象函数与虚

函数,一般是在设计一个时使用,它将接口函数设置为函数后,只提供子类去继承并实现,以形成多态,除此以外不提供任何其他功能,我们称这种类为抽象(abstract)。...【函数声明语法】 virtual 函数声明 = 0; 【函数特征】 1、只有声明,没有实现代码。 2、含有函数称为抽象(abstract)。不能被实例化,只能被继承。...3、继承抽象意义就是提供族类公共接口。 4、子类继承函数,如果未实现,子类仍然为抽象,仍然不能被实例化。 【虚函数若干限制】 1、只有成员函数才能声明为虚函数。...4、构造函数不能是虚函数,构造时,对象创建尚未完成。构造完成后,能算一个名符其实对象。 5、函数可以是虚函数且通常声明为虚函数。...(2, 4, 8); s->draw(); // delete 指针,调用函数 delete s; return 0; } 以上代码演示了函数定义,但上面代码存在一个问题,我们先看一下运行结果

18730

构造函数函数

一、构造函数函数由来 数据成员不能在声明时候初始化,为了解决这个问题? 使用构造函数处理对对象初始化。...构造函数是一种特殊成员函数,与其他函数不同,不需要用户调用它,而是创建对象时候自动调用。函数是对象不再使用时候,需要清理资源时候调用。...三、函数 函数和构造函数作用相反,释放对象使用资源,并销毁非static成员。 (1)内存泄漏 下面代码有何隐患?...其实也是一样,上述代码就会有内存泄漏风险。如何解决呢?看下述代码。 在上述代码中,我们在函数中,添加delete函数。解决了内存泄漏问题,但是还存在其他问题。...4、当函数中存在手动释放资源时侯,一定要注意之前是否释放过,以及以后是否有其他操作会释放。

1.8K20
  • 从零开始学C++之虚函数与多态(二):函数抽象、虚函数

    构造函数不能是虚函数函数可以是虚函数 1、抽象不能用于直接创建对象实例,可以声明抽象指针和引用 2、可使用指向抽象指针支持运行时多态性 3、派生中必须实现函数,否则它仍将被看作一个抽象...Shape抽象,Draw函数函数,Circle, Square, Rectangle都重新实现了Draw,在这里把Shape函数声明为虚函数,那么delete 指针,会调用派生函数...函数为虚函数,所有派生函数都是虚函数 构造函数不得是虚函数 如果要操作具有继承关系动态对象,最好使用虚函数。...#include  using namespace std; // 对于一个没有任何接口,如果想要将它定义成抽象,只能将虚函数声明为 // 通常情况下在函数不需要实现...如果想要将它定义成抽象,只能将虚函数声明为 // 通常情况下在函数不需要实现 // 例外是函数要给出实现。

    1.3K00

    C++构造函数函数

    C++中每个都有其构造与函数,它们负责对象创建和对象清理和回收,即使我们不写这两个,编译器也会默认为我们提供这些构造函数。...下面仍然是通过反汇编方式来说明C++中构造和函数是如何工作。...编译器是否真的会默认提供构造与函数 在一般讲解C++书籍中都会提及到当我们不为提供任何构造与函数时编译器会默认提供这样六种成员函数:不带参构造,拷贝构造,“=”重载函数函数,以及带const...何时调用函数 对于函数调用我们仍然分为以下几个部分: 局部类对象:当对象所在生命周期结束后,即一般语句块结束或者函数结束时会调用 全局对象和静态对象:当程序结束时会调用构造函数...,但是接着执行函数函数中定义对象,接受返回值得这块内存一直等到它所在语句块结束才调用 如果不要这个返回值时又如何呢,下面的代码说明了这个问题 int main() {

    1.6K10

    使用Python构造函数函数

    1、问题背景当使用Python时,可以使用构造函数函数来初始化和清理实例。构造函数在创建实例时自动调用,而函数在删除实例时自动调用。...在上面的代码示例中,Person具有一个构造函数__init__和一个函数__del__。...函数__del__在Person实例被删除时被调用,它将实例的人口计数population减1。...问题是,如果我在程序中显式地删除Person实例,函数__del__是否会被自动调用,或者我是否需要在“main”程序/中添加一些东西,如上面的代码示例所示?...2、解决方案函数__del__会在垃圾回收器收集对象时自动调用,而不是在丢失对对象最后一个引用时,也不是在执行del object时调用。

    15610

    C++核心准则​讨论:将函数设为公共和虚拟,或受保护和非虚拟

    函数应该是虚函数吗?也就是说,是否应该允许通过指向指针进行销毁?如果是,则base函数必须是公共才能被调用,否则虚拟调用它会导致未定义行为。...否则,应该对其进行保护,以便只有派生才能在自己函数中调用它,这个函数也应该是非虚,因为它不需要虚拟地运行。...如果Base函数是公共和非虚拟(默认值),则可能会意外地在实际指向派生对象指针上调用它,在这种情况下,尝试删除行为是不确定。...这种情况导致较早编码标准对所有函数都必须是虚拟提出了全面的要求。这太过分了(即使是常见情况);相反,规则应该是当且仅当函数是公共时,才将它们虚函数化。...因此,如果可以调用(即是公共函数,则它是虚拟,否则是非虚拟

    1.1K20

    函数? vptr? 指针偏移?多态数组? delete 指针 内存泄漏?崩溃?

    5、 在继承机制中,构造函数函数具有一种特别机制叫 “层链式调用通知” 《 C++编程思想 》 C++标准规定:函数必须声明为virtual, 如果你不声明,那么"层链式调用通知"这样机制是没法构建起来....从而就导致了函数被调用了,而派生函数没有调用这个问题发生....将函数改成虚函数,fun() 最好也改成虚函数,只要有一个虚函数大小就为一个vptr ,此时和派生大小都是4个字节,p也指向派生首地址,问题解决,参考规则3。...也是论坛经常讨论,也就是说delete 指针(在指针没有偏离情况下) 会不会造成内存泄漏问题,上面说到如果此时函数为虚函数,那么是不会内存泄漏,如果不是则行为未定义。.../test )检测,并没有内存泄漏,和派生函数也正常被调用。

    1K20

    函数? vptr? 指针偏移?多态数组? delete 指针 内存泄漏?崩溃?

    5、 在继承机制中,构造函数函数具有一种特别机制叫 “层链式调用通知” 《 C++编程思想 》 C++标准规定:函数必须声明为virtual, 如果你不声明,那么"层链式调用通知"这样机制是没法构建起来....从而就导致了函数被调用了,而派生函数没有调用这个问题发生....将函数改成虚函数,fun() 最好也改成虚函数,只要有一个虚函数大小就为一个vptr ,此时和派生大小都是4个字节,p也指向派生首地址,问题解决,参考规则3。...也是论坛经常讨论,也就是说delete 指针(在指针没有偏离情况下) 会不会造成内存泄漏问题,上面说到如果此时函数为虚函数,那么是不会内存泄漏,如果不是则行为未定义。.../test )检测,并没有内存泄漏,和派生函数也正常被调用。

    95500

    C++编程经验(2):为虚做虚函数必要性

    这个要提一下,如果记不住就记住:如果不做虚函数,会有内存泄漏 解释 定义一个指针p,在delete p时,如果函数是虚函数,这时只会看p所赋值对象,如果p赋值对象是派生对象,...就会调用派生函数;如果p赋值对象是对象,就会调用函数,这样就不会造成内存泄露。...如果函数不是虚函数,在delete p时,调用函数时,只会看指针数据类型,而不会去看赋值对象,这样就会造成内存泄露。 多少学点设计模式就清楚了。...接下来是一个子类 class Inherit :public Base{ //此处省去,一切从简 }; //重点看调用 int main() { Base *p = new Inherit; //这种方式调用...,这时候有没有虚就不一样了 delete p; Base *q = new Base; delete q; return 0; }

    57710

    函数

    抽象定义: 称带有函数抽象 抽象作用 抽象主要作用是将有关操作作为结果接口组织在一个继承层次结构中,由它来为派生提供一个公共根,派生将具体实现在其中作为借口操作...使用抽象时注意: 抽象只能作为来使用,其函数实现由派生给出。如果派生中没有重新定义函数,而只是继承函数,则这个派生仍然是一个抽象。...如果派生中给出了函数实现,则该派生就不再是抽象了,它是一个可以建立对象具体抽象是不能定义对象。...核心理念就是通过访问派生定义函数。 在有动态分配堆上内存时候,函数必须是虚函数,但没有必要是。 友元不是成员函数,只有成员函数才可以使虚拟,因此友元不能是虚拟函数。...但可以通过让友元函数调用虚拟成员函数来解决友元虚拟问题。 函数应当是虚函数,将调用相应对象类型函数。因此,如果指针指向是子类对象,将调用子类函数,然后自动调用函数

    1.1K20

    virtual

    此时,函数被隐藏(注意别与覆盖混淆)。 函数 C++语言为我们提供了一种语法结构,通过它可以指明,一个虚拟函数只是提供了一个可被子类型改写接口。...原理: 如果父当中定义了虚函数,那么父函数表当中就会有一个父函数指针,指向是父函数,子类虚函数表当中也会产生一个子类函数入口指针,指向是子类函数...函数实现原理 在虚函数原理基础,虚函数表中,虚函数地址是一个有意义值,如果是函数就实实在在写一个0 含有函数被称为抽象 含有函数被称为抽象。...哪怕中只有一个函数,那么这个也是一个抽象函数没有函数体,所以抽象不允许实例化对象,抽象子类也可以是一个抽象。...抽象子类只有把抽象中所有函数都做了实现才可以实例化对象。 仅含有函数称为接口 如果在抽象中仅含有函数而不含其他东西,我们称之为接口

    65150

    轻松搞定面试中“虚”

    声明函数一般形式是                             virtual 函数类型 函数名 (参数表列)=0; 也称抽象,凡是包含函数都是抽象。...因为函数是不能被调用,包含函数是无法建立对象抽象作用是作为一个共同,或者说,为一个族提供一个公共接口。 3.为什么有的函数需要设为virtual?...是否每个函数都要设置成virtual?是否可以将函数设置成内联函数。 这样做是为了当用一个指针删除一个派生对象时,派生函数会被调用。...所以,只有当一个被用来作为时候,才把函数写成虚函数。 可以。 4.函数是否可以是函数? 可以,当需要定义一个抽象,如果其中没有其他合适函数,可以把函数定义为。...在时候会首先调用子类函数掉对象中子类部分,然后在调用函数部分,如果在函数里面调用虚函数,会导致其调用已经子类对象里面的函数,这是非常危险

    66520

    C++-编写String构造函数函数和赋值函数

    浏览量 2 说到这题就想到了我很早之前一次面试,就是由于这题被面试官说一文不值(当然说得也不错),这题是c++里面的基本题目,据说能够完整写出来的人,基础就达到了及格以上水平,在后续面试里面就没有看到这样题目...已知String原型为: class String { public: String(const char *str = NULL); // 普通构造函数 String(const String...&other); // 拷贝构造函数 ~ String(void); // 函数 String & operator =(const String &other); // 赋值函数 private...: char *m_data; // 用于保存字符串 }; 关于这道题目的解答,我在网上看到一个较完整就直接发给大家看一下,如果你有些慨念不清楚,比如什么是赋值函数,它怎么样实现,以及功能是什么...m_data = new char[length+1]; // 若能加 NULL 判断则更好 strcpy(m_data, str); } } // String函数

    59410

    C++核心准则C.127:包含虚函数应该有虚函数或保护函数

    C.127: A class with a virtual function should have a virtual or protected destructor C.127:包含虚函数应该有虚函数或保护函数‍...包含虚函数通常(大多数情况下)通过指向指针使用。通常,最后一个使用者必须通过指向指针调用delete操作,通常是指向智能指针,因此函数应该是公开函数。...稍微特殊一些情况是:如果不希望支持通过指向指针销毁对象,函数应该是保护非虚函数。参见C.35。...包含虚函数函数要么是公开函数,要么是保护非虚函数。...提示针对包含虚函数却没有虚函数销毁操作。

    76820

    C++核心准则C.35:函数要么是公开函数,要么是保护非虚函数

    C.35: A base class destructor should be either public and virtual, or protected and nonvirtual 函数要么是公开函数...为了避免无定义行为。如果函数是公有的,那么调用侧代码就会尝试使用指针销毁派生对象,在函数为非虚函数时其结果时没有定义。...如果函数时保护,那么调用侧代码就无法通过类型指针销毁派生对象,这是函数就没有必要一定是虚函数函数是保护而不是私有的,这样派生函数才能调用它。...通常,设计者不会知道在函数中应该执行什么样动作。...我们可以想象一种需要保护函数函数情况:当希望允许派生对象(只有这个类型)通过指针销毁另外一个对象(不是它自己)时。但是我们还没有在实际开发中遇到这种情况。

    1K20

    【C++】多态

    ,对于自定义类型delete会做是: 1. 在要释放对象空间执行函数,完成对象中资源清理工作 2....但是: 重写不是要求和派生函数名字一样吗,可是它们两个函数名字并不一样啊。...包含函数叫做抽象抽象不能实例化出对象。 派生继承后也不能实例化出对象,只有重写函数,派生才能实例化出对象。...函数规范了派生必须重写(不重写就不能实例化),另外函数更体现出了接口继承。 下面通过一些例子帮助大家理解理解: 这里Car这个就是一个抽象,因为它包含函数。...我们继续: 另外上面还说到抽象被继承后子类也不能实例化出对象: 因为这里子类还是一个抽象,它也包含函数,是它继承下来嘛。

    11010

    C++函数抽象

    1.2虚函数继承中,函数一般都是虚函数。当中有虚函数时候,函数也要定义为虚函数。...如果不定义虚函数,当删除一个指向派生对象指针时,会调用函数,派生函数未被调用,造成内存泄露。...虚函数工作方式是:最底层派生函数最先被调用,然后各个函数被调用。这样,当删除指向派生指针时,就会首先调用派生函数,不会有内存泄露问题了。...一般情况下,如果类中没有虚函数,就不用去声明虚函数。当且仅当里包含至少一个虚函数时候才去声明虚函数。只有当一个被用来作为时候,才有必要将函数写成虚函数。...实现了Base函数函数,同时注意到,企图去实例化抽象,编译器会报错。

    1.5K20

    C++重要知识点小结---2

    这种类成为抽象。 一个抽象至少具有一个函数。所谓函数是指被标明为不具体实现虚成员函数。...该声明是为派生而保留位置。 一个抽象不能有实例对象,即不能由该类抽象来制造一个对象。 函数是在中为子类保留一个位置,以便子类用自己实在函数定义来重载之。...如果在中没有保留位置,则就没有重载。 函数是一个没有定义函数语句函数函数值是0.派生必须为每一个函数提供一个相应函数定义。...构造函数按下列顺序被调用: 任何虚拟构造函数按照它们被继承顺序构造; 任何非虚拟构造函数按照它们被继承顺序构造; 任何成员对象构造函数按照它们声明顺序调用; 自己构造函数。...如果函数是虚函数,有多态支持,r1调用Circle对象函数,Circle对象函数默认调用父Range函数,保证Circle和Range对象内容都得到清除。

    70470
    领券