c++ - 下面的程序在 C++ 中如何工作?

标签 c++ class pointers

我刚刚创建了 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();  
} 

最佳答案

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

B) 因为您没有调用虚拟方法,所以很容易解释为什么未定义的行为实际上会这样做(而且我已经在我能找到的几乎所有编译器下测试了这一点)。

在 C++ 中,调用成员方法与调用带有隐藏“this”变量的成员是等价的(如果不是在定义中,实际上也是如此)。如果方法是虚拟的,它必须通过 vftable,但对于非虚拟方法则不需要。

所以

Foo::Bar(){}

大致相当于

Foo_Bar(Foo *this){}

在调用代码中

Foo *foo = new Foo();
foo->bar();

第二行大致相当于

Foo_Bar(foo);

现在,这里进行了一些简化,正如我所说,其中一些可能是实现细节而不是规范。但是,该行为是正确的(尽管依赖它是错误的)。

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

void Foo::Bar(){printf("Hello, world!\n");}

和调用代码:

Foo *foo = 0;
foo->Bar();

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

Foo *foo = 0;
Foo::Bar(foo);

这意味着我们正在调用以下方法的等价物:

void Foo_Bar(Foo* this)
{ printf("Hello, world\n"); }

现在,有了这个方法,我们实际上并没有取消 this 指针!因此,很清楚为什么在这种情况下该方法会起作用而不会失败。

这样做的实际结果是,在空指针上调用非虚拟方法(该方法不会取消引用 a 成员)通常会导致这种观察到的行为。但是,依赖任何未定义的行为基本上是邪恶的。

关于c++ - 下面的程序在 C++ 中如何工作?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/2564952/

相关文章:

C++ Cstring拆分

c++ - 将 String^ 转换为 std::string(基本字符串)-> 错误。我怎样才能解决这个问题?

C++ 部分特化不适用于不同大小的特征矩阵

c++ - FSM 在 C++ 中使用成员函数指针

c++ - 数据结构——指向自身的 C++ 指针

c - 如何在 C 中制作 char** 的副本?

c++ - 请解释一个功能单例(C++)

JavaCompiler - 设置编译类输出文件夹

javascript - 在 anchor 中动态设置类不起作用?

java - 第一个Java程序(计算器)问题