【问题标题】:C++ i can`t understand why it call "father class static function" and it call just father destructorC ++我不明白为什么它调用“父类静态函数”而它只调用父析构函数
【发布时间】:2016-10-15 03:33:00
【问题描述】:

我有下一个代码:

#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() ah() ch() A() A() ah() ah() ~A() ~A() ~C() ~A( ) ~A() 并且它不打印 A() A() ah() ch() A() A() ah() ch() ~A() ~A() ~C() ~A( ) ~C()。谁能帮帮我?

【问题讨论】:

  • 看起来大约 90% 的代码(以及 90% 的输出)与问题无关。
  • TL;DR:析构函数应该是虚拟的,静态函数不能是虚拟的。
  • 尊重在这里帮助您的人的时间,并花一点时间删除您做不感到困惑的部分,然后再询问其余部分。
  • 我很抱歉提出不好的问题。我是stackoverflow的新手。我会尽量不重蹈覆辙。
  • “我不明白为什么”是你不问问题的方式(在 SO 或其他地方)。您应该解释为什么您认为您的代码具有明确定义的行为以及这种行为应该是什么。

标签: c++ inheritance polymorphism destructor


【解决方案1】:

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

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

其实因为h()其实是一个static类函数,那么

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

完全等同于:

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

编译器甚至不费心编译检索arr[0] 和arr[1] 指针的代码,因为它们无关紧要。 this 不被 static 类方法使用,当然,所以没有必要浪费时间弄清楚 this 应该是什么。

【讨论】:

  • 只是为了澄清,我正在解决引用的具体点,即实际输出是“...ah() ah()...”而不是 OP 所期望的,即“.. .ah() ch()...".
【解决方案2】:

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

解决方法:不要通过基类指针删除对象,或者将基类的析构函数设为虚函数。

其次,调用arr[0]-&gt;h()时不会打印ch(),因为arr[0]的静态类型不是C*,而是A*。不使用虚拟调度,因为该函数不是虚拟的。它不能是虚拟的,因为它是一个静态成员函数。静态成员函数不能被覆盖。

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

【讨论】:

  • 我正在准备考试,我试图解决一些问题。老师给我们一些代码示例,我们需要编写代码在做什么。你说 arr[0] 是 A* 类型,所以我问为什么它也为 arr[1] 调用 A 和 C 析构函数?
  • 你的意思是delete arr[1]; 会同时调用A 和C 析构函数吗?好吧,这不是您在输出中看到的。更加注意哪个输出来自哪个语句。使用调试器单步执行代码。
  • 我明白了。 ~C() 和 ~A() 来自 C c 析构函数。谢谢。
猜你喜欢
  • 2013-08-08
  • 1970-01-01
  • 2011-09-07
  • 2011-02-07
  • 2011-09-24
  • 2015-04-24
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多