在C ++中转换指针后访问类的成员

时间:2015-06-01 03:40:14

标签: casting c++-cli

我是C ++的新手。 谁能告诉我为什么以下源代码运行良好?

#include <iostream>

using namespace std;

class A{
public:
    A(){ cout << "create a" << endl; }
    void sayGoodbye() { cout << "goodbye" << endl; }
};

class B{
public:
    B() { cout << "create b" << endl; }
    void sayHello() { cout << "hello" << endl; }
};

int main(array<System::String ^> ^args)
{
    A* a = new A();

    ((B*)a)->sayHello();
    a->sayGoodbye();

    return 0;
}

输出:

create a
hello
goodbye

我想知道为什么a可以通过这样的方式进行访问B :: sayHello? 它可以通过这种方式访问​​任何类的每个公共成员吗?

5 个答案:

答案 0 :(得分:4)

是的,你可以。

但是,不,你不能。

当你使用像这样的C风格的演员表时,你向计算机承诺你知道你在做什么,并且演员表是有效的。当 有效时,你没事。如果不是,那就是你的错误。

在这种情况下,它不是,这是你的错。

现在,你可以问为什么它“运行良好”,但这是偶然的:那是纯粹的机会。程序编译完成后,如果您真正访问无效内存,它只会崩溃或谋杀您的继子。在这种特殊情况下,您无法访问无效内存。

但这并不意味着你是对的。

不要这样做。

答案 1 :(得分:2)

This不是您问题的答案,但在使用指针投射时,它可以为您提供更多知识和选项:

您可以看到以下几种施法技术:

static_cast
dynamic_cast
const_cast
reinterpret_cast
C-style cast (type)value
Function-style cast type(value)

答案 2 :(得分:1)

就我而言,我使用dynamic_cast来检查这个转换问题。在向下铸造的情况下它也很有用。 但是在向下转换中有一个问题就是我们必须有多态类类型。

答案 3 :(得分:0)

由于您为类A和B定义的函数不依赖于存储在这些类中的任何数据,因此计算机不必读取任何内容来运行这些函数并且它们能够执行。

一般情况下,如果sayHello方法需要读取存储在B类上的数据,那么你的演员阵容会导致段错误或其他一些严重的问题,因为这会让计算机读入内存它会被告知被分配以适合类型B的对象,但由于对象属于类型A,因此不是这种情况。

答案 4 :(得分:0)

sayHello方法不访问类B中的任何数据成员。此外,((B*)a)->sayHello();被编译为类似于call-to-mangled-sayHello-member-function-of-B(this)的内容。因此,将通过将指针传递给B的对象来调用类B成员函数sayHello,并且该指针未在sayHello方法中使用。因此,它将适用于这种情况。

((B*)0)->sayHello();
((B*)1)->sayHello();
((B*)2)->sayHello();

事实上,上述所有电话都有效。 sayHello会收到一个地址为0,1,2的this指针。由于sayHello没有访问B的任何数据成员,所以它们会起作用。如果sayHello访问任何非静态数据成员,那么就会出现大崩溃。通常,行为是不确定的。 如果sayHello是虚拟的,那么就会出现真正的问题。因为,在这种情况下,需要在内存中有效的对象来在运行时解析被调用的函数。