以下程序如何在c ++中运行?

Ete*_*ner 1 c++ pointers class

我刚刚创建了2个具有未定义行为的指针,并尝试调用没有创建对象的类成员函数?

我不明白这个?

#include<iostream>

using namespace std;

class Animal
{
public:
  void talk()
  {
    cout<<"I am an animal"<<endl; 
  }
};

class Dog : public Animal
{  
public:
  void talk()
  {
    cout<<"bark"<<endl; 
  }
};

int main()
{
  Animal * a;
  Dog * d;

  d->talk();
  a->talk();  
} 
Run Code Online (Sandbox Code Playgroud)

kyo*_*ryu 10

A)这是未定义的行为.任何行为都可能发生.

B)因为你没有调用虚方法,所以很容易解释为什么未定义的行为实际上是这样做的(我在几乎所有我能找到的编译器下测试过这个).

在C++中,调用成员方法与使用隐藏的'this'变量调用成员是等效的(实际上,如果不是在定义中).如果方法是虚拟的,则必须通过vftable,但不能通过非虚方法.

所以

Foo::Bar(){}
Run Code Online (Sandbox Code Playgroud)

是粗略的等价物

Foo_Bar(Foo *this){}
Run Code Online (Sandbox Code Playgroud)

并在调用代码中

Foo *foo = new Foo();
foo->bar();
Run Code Online (Sandbox Code Playgroud)

第二行大致是道德等同于

Foo_Bar(foo);
Run Code Online (Sandbox Code Playgroud)

现在,这里有一些简化,正如我所说,其中一些可能是实现细节而不是规范.但是,行为成立(尽管依赖它是一个错误).

但是,鉴于前面的内容,请看一个实现:

void Foo::Bar(){printf("Hello, world!\n");}
Run Code Online (Sandbox Code Playgroud)

并调用代码:

Foo *foo = 0;
foo->Bar();
Run Code Online (Sandbox Code Playgroud)

正如我们所说,这大致相当于(因为我们是非虚拟的):

Foo *foo = 0;
Foo::Bar(foo);
Run Code Online (Sandbox Code Playgroud)

这意味着我们调用的方法与以下方法相同:

void Foo_Bar(Foo* this)
{ printf("Hello, world\n"); }
Run Code Online (Sandbox Code Playgroud)

现在,给定这个方法,我们实际上并没有消除这个指针!因此,很明显为什么,在这种情况下,该方法将起作用而不会失败.

这样做的实际结果是,在空指针上调用非虚方法,其中方法不解析成员,通常会导致这种观察到的行为.但是,依赖任何未定义的行为基本上都是邪恶的.


Jer*_*fin 8

当你做一些有不确定行为的事情时,任何事情都可能发生 - 包括它似乎有效.看起来这就是在这种情况下发生的事情.

  • @Srinivasa:在****情况下,未定义的行为有效.**没有**.在_any_情况下,它可能会出现,但就是这样. (8认同)
  • +1用于回答看似实际的问题. (4认同)