C ++我不能理解为什么它调用“父类静态函数”并且它只调用父析构函数

时间:2016-06-14 11:58:44

标签: c++ inheritance polymorphism destructor

我有下一个代码:

#include <iostream>

using namespace std;

class A{
public:
    A() { cout << "A() ";}
    virtual void f()=0;
    virtual void g() { cout << "ag() ";}
    static void h() { cout << "ah() ";}
    void i() { cout << "ai() ";}
    ~A() { cout << "~A() "; }
};

class B: public A{
    void f() { cout << "bf() ";}
public:
    void g() { cout << "bg() ";}
};

class C: public B{
public:
    static void h() { cout << "ch() "; }
    void g() { cout << "cg() ";}
    ~C() { cout << "~C() ";}
};

void f1(){
    B b;
    C c;
    b.h();
    c.h();  
    A* arr[2] = { new B ,new C};
    arr[0]->h();
    arr[1]->h();
    delete arr[0];
    delete arr[1];
}


int main(){
    f1();
    return 0;
}

我无法理解为什么打印A()A()啊()ch()A()A()啊()啊()~A()~A()~C()~A( )~A()并且它不打印A()A()啊()ch()A()A()啊()ch()~A()~A()〜C()~A( )~C()。任何人都可以帮助我吗?

2 个答案:

答案 0 :(得分:1)

首先,您忘记声明A虚拟的析构函数。因此,通过A指针删除派生对象具有未定义的行为。未定义行为的一个可能结果是不打印~C()(并且内存泄漏)。除非您忘记启用警告,否则一个体面的编译器会警告您。

解决方案:不要通过基类指针删除对象,也不要使基类的析构函数为虚拟。

其次,当您致电ch()时,不会打印arr[0]->h(),因为arr[0]的静态类型不是C*,而是A*。不使用虚拟分派,因为该功能不是虚拟的。它不能是虚拟的,因为它是一个静态成员函数。无法覆盖静态成员函数。

解决方案:调整您的期望。

答案 1 :(得分:0)

这是因为arr是一个包含指向A类实例的指针的数组。

因此,调用arr[0]->h()会调用A::h()h()不是虚拟类方法。您显然了解虚拟继承如何工作以及虚函数如何覆盖其基类版本。但是,要使虚拟继承起作用,实际上必须使用virtual关键字声明该函数。您没有看到用于声明virtual类方法的h()关键字,那么为什么您希望h()像虚函数一样工作?

事实上,因为h()实际上是static类函数,所以

arr[0]->h();
arr[1]->h();

完全等同于:

A::h();
A::h();

编译器甚至懒得编译检索arr[0]arr[1]指针的代码,因为它们无关紧要。当然,this类方法并未使用static,因此无需浪费时间来确定this应该是什么。