我有下一个代码:
#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()。任何人都可以帮助我吗?
答案 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
应该是什么。