struct A { bool testA(int) { std::cout << "A" << std::endl; return true; };};struct B { void testB() { std::cout << "B" << std::endl; };};int main() { A a; ((B*)(&a))->testB(); return 0;}
struct A {
bool testA(int) {
std::cout << "A" << std::endl;
return true;
};
struct B {
void testB() {
std::cout << "B" << std::endl;
int main() {
A a;
((B*)(&a))->testB();
return 0;
}
为什么可以用指向A类对象的指针调用B类对象的成员函数而不引发异常?
hgb9j2n61#
C核心语言不使用异常来表示程序员编写了违反语言规则的代码,除非在非常特定的情况下,可以在没有运行时开销的情况下检测到违规,例如std::bad_new_array_length。相反,通常的方法是“未定义的行为”。通常不能期望实现检查您是否遵循规则,因为这样做会使代码变慢。例如,在成员函数调用的情况下,捕获如OP所示的bug的一种策略是为 every 对象分配vptr和RTTI信息,而不仅仅是多态类型的对象。然后,every 成员函数调用,在运行时,可以查找类型信息,并将其与静态需要的类型(在本例中,B)进行比较。请注意,这种实现策略将增加每个对象的大小,增加每个可执行映像的大小(由于RTTI信息的生成),并增加每个成员函数调用所花费的时间。换句话说,即使程序是正确的,它也会显著恶化程序的性能。因此,C标准并没有强制执行这种pessimization,而是允许实现在假设对象表达式真的表示一个适当类型的对象的情况下编译成员函数调用。如果你违反了这个规则,你会得到你所得到的。(Some实现使用这种自由来执行积极的“时间旅行”优化,但我不会在这里进入。
std::bad_new_array_length
B
1条答案
按热度按时间hgb9j2n61#
C核心语言不使用异常来表示程序员编写了违反语言规则的代码,除非在非常特定的情况下,可以在没有运行时开销的情况下检测到违规,例如
std::bad_new_array_length
。相反,通常的方法是“未定义的行为”。通常不能期望实现检查您是否遵循规则,因为这样做会使代码变慢。例如,在成员函数调用的情况下,捕获如OP所示的bug的一种策略是为 every 对象分配vptr和RTTI信息,而不仅仅是多态类型的对象。然后,every 成员函数调用,在运行时,可以查找类型信息,并将其与静态需要的类型(在本例中,
B
)进行比较。请注意,这种实现策略将增加每个对象的大小,增加每个可执行映像的大小(由于RTTI信息的生成),并增加每个成员函数调用所花费的时间。换句话说,即使程序是正确的,它也会显著恶化程序的性能。因此,C标准并没有强制执行这种pessimization,而是允许实现在假设对象表达式真的表示一个适当类型的对象的情况下编译成员函数调用。如果你违反了这个规则,你会得到你所得到的。(Some实现使用这种自由来执行积极的“时间旅行”优化,但我不会在这里进入。