我在C ++中遇到一些奇怪的事情,但我不知道为什么?
我有一个这样的课程
头文件
class foo
{
public:
void call_foo();
int get_foo();
int get_foo(int val);
};
这是cpp文件
#include "foo.h"
#include <iostream>
using namespace std;
void foo::call_foo()
{
int i = 0;
int j = 33;
cout << i + j << endl;
cout << "Hello, Foo" << endl;
}
int foo::get_foo(int val)
{
int a = 345;
int rc = val + a;
cout << rc << endl;
return rc;
}
int foo::get_foo()
{
int a = 100;
int d = 23;
int rc = a + d;
cout << rc << endl;
return rc;
}
我使用代码进行测试,如下所示
int main()
{
int* val = new int[100];
foo* foo_ptr;
foo_ptr = (foo*)val;
foo_ptr->call_foo();
foo_ptr->get_foo();
foo_ptr->get_foo(100);
delete [] val;
return 0;
}
然后我编译并执行它。
clang++ foo.cpp main.cpp
Apple LLVM 5.0版(clang-500.2.79) os x 10.9
一个int指针转换为一个对象指针,然后调用它的方法,它工作!太奇怪了! 有人知道发生了什么事吗?
我写了一篇关于my blog的文章,关于为什么它在我的理解中有效,谢谢大家!关于对象结构,虚函数表。只是中文版:))
答案 0 :(得分:2)
您遇到的问题称为未定义行为。
未定义的行为意味着“任何事情都可能发生”。 Anything 在这里包含你的代码工作的错觉,做了你期望它做的事情,或没有做你期望它做的事情 - 比如崩溃。
唤起未定义行为的代码总是错误的代码。如果只是因为你无法预测会发生什么,你就不能依赖未定义的行为。
现在在这种情况下,调用方法可能看起来有效的原因是因为实际上类的实例没有为每个非static
方法获取它自己的代码副本。相反,在foo
的所有实例之间共享一个代码副本。指向该代码的指针永远不会改变,因此当您(错误地)解析指向 - foo
的指针然后通过该指针调用其中一个方法时,实际调用的实际方法实际上是调用的。但这仍然是未定义的行为,您需要修复代码。
答案 1 :(得分:1)
这是未定义的行为,您的程序格式不正确。就语言规范而言,任何事情都可能发生。
它恰好似乎工作,因为没有成员函数访问任何属于foo
对象的特定实例的数据。他们所做的就是分配本地数据并访问cout
。
答案 2 :(得分:0)
它不起作用,它有不确定的行为。
但是,这些函数不是虚拟的,并且该对象没有数据成员,因此您的程序可能实际上不会触及无效内存,因此与调用有效对象上的函数具有相同的效果
答案 3 :(得分:0)
你的类没有成员也没有虚函数所以当你通过任意指针调用一个成员函数它会“工作”,因为你有一个静态绑定的函数调用,并且不做任何无效的内存访问。如果您尝试调用虚函数或访问成员变量,则会发生错误。