C++ 我不明白为什么它调用 "father class static function" 而它只调用父析构函数
C++ i can`t understand why it call "father class static function" and it call just father 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() ah() ch() A() A() ah() ah() ~A() ~A() ~C() ~ A() ~A() 并且它不打印 A() A() ah() ch() A() A() ah() ch() ~A() ~A() ~C() ~ A()〜C()。谁能帮帮我?
这是因为 arr
是一个包含指向 A
class 个实例的指针的数组。
因此,调用 arr[0]->h()
会调用 A::h()
。 h()
不是虚拟 class 方法。您显然了解虚拟继承的工作原理以及虚拟函数如何覆盖其基础 class 版本。但是,要使虚拟继承起作用,实际上必须使用 virtual
关键字声明该函数。您没有看到用于声明 h()
class 方法的 virtual
关键字,是吗,那么您为什么期望 h()
像虚函数一样工作?
其实因为h()
其实是一个static
class函数,那么
arr[0]->h();
arr[1]->h();
完全等同于:
A::h();
A::h();
编译器甚至懒得编译检索 arr[0]
和 arr[1]
指针的代码,因为它们是不相关的。 this
不被 static
class 方法使用,当然,所以没有必要浪费时间弄清楚 this
应该是什么。
首先,您忘记声明 A
virtual 的析构函数。因此,通过 A
指针删除派生对象具有未定义的行为。未定义行为的一种可能结果是 ~C()
未打印(并且内存已泄漏)。一个体面的编译器会警告你这一点,除非你忘记启用警告。
解决方法:不要通过基class指针删除对象,或者将基class的析构函数设为虚
其次,调用arr[0]->h()
时不会打印ch()
,因为arr[0]
的静态类型不是C*
,而是A*
。不使用虚拟分派,因为函数不是虚拟的。而且它不能是虚拟的,因为它是一个静态成员函数。不能覆盖静态成员函数。
解决方法:调整你的预期。
我有下一个代码:
#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()。谁能帮帮我?
这是因为 arr
是一个包含指向 A
class 个实例的指针的数组。
因此,调用 arr[0]->h()
会调用 A::h()
。 h()
不是虚拟 class 方法。您显然了解虚拟继承的工作原理以及虚拟函数如何覆盖其基础 class 版本。但是,要使虚拟继承起作用,实际上必须使用 virtual
关键字声明该函数。您没有看到用于声明 h()
class 方法的 virtual
关键字,是吗,那么您为什么期望 h()
像虚函数一样工作?
其实因为h()
其实是一个static
class函数,那么
arr[0]->h();
arr[1]->h();
完全等同于:
A::h();
A::h();
编译器甚至懒得编译检索 arr[0]
和 arr[1]
指针的代码,因为它们是不相关的。 this
不被 static
class 方法使用,当然,所以没有必要浪费时间弄清楚 this
应该是什么。
首先,您忘记声明 A
virtual 的析构函数。因此,通过 A
指针删除派生对象具有未定义的行为。未定义行为的一种可能结果是 ~C()
未打印(并且内存已泄漏)。一个体面的编译器会警告你这一点,除非你忘记启用警告。
解决方法:不要通过基class指针删除对象,或者将基class的析构函数设为虚
其次,调用arr[0]->h()
时不会打印ch()
,因为arr[0]
的静态类型不是C*
,而是A*
。不使用虚拟分派,因为函数不是虚拟的。而且它不能是虚拟的,因为它是一个静态成员函数。不能覆盖静态成员函数。
解决方法:调整你的预期。