Warning: file_get_contents(/data/phpspider/zhask/data//catemap/6/cplusplus/139.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
C++ C++;:指针传递后包含不同的地址_C++_Pointers_Visual Studio 2013_Multiple Inheritance_Memory Address - Fatal编程技术网

C++ C++;:指针传递后包含不同的地址

C++ C++;:指针传递后包含不同的地址,c++,pointers,visual-studio-2013,multiple-inheritance,memory-address,C++,Pointers,Visual Studio 2013,Multiple Inheritance,Memory Address,所以我有一些类似这样的代码: #include <iostream> using namespace std; class Base1 {}; class Base2 {}; class A { public: A() {} void foo(Base2* ptr) { cout << "This is A. B is at the address " << ptr << endl; } }; A *gl

所以我有一些类似这样的代码:

#include <iostream>

using namespace std;

class Base1 {};
class Base2 {};

class A
{
public:
    A() {}
    void foo(Base2* ptr) { cout << "This is A. B is at the address " << ptr << endl; }
};

A *global_a;

class B : public Base1, public Base2
{
public:
    B() {}
    void bar()
    {
        cout << "This is B. I am at the address " << this << endl;
        global_a->foo(this);
    }
};

int main()
{
    global_a = new A();
    B *b = new B();

    b->bar();

    system("pause");
    return 0;
}
#包括
使用名称空间std;
类Base1{};
类Base2{};
甲级
{
公众:
A(){}

void foo(Base2*ptr){cout
B
源于
Base1
Base2
,因此它包含
Base1
Base2
包含的所有数据,以及
B
添加到它们上面的所有数据

B::bar()
将指向自身
Base2
部分的指针传递给
a::for()
,而不是自身的
B
部分。
B::bar()
正在打印
B
部分的根地址,而
a::foo()
正在打印
Base2
部分的根地址。您正在传递相同的对象,但它们在该对象中是不同的地址:

如果
B
未添加任何新数据,则其基址可能与其最近祖先的根地址相同(原因如下):

不要依赖于此。编译器可能会在类之间添加填充,例如:

始终将各个部分视为独立的(因为它们在逻辑上是独立的)。仅仅因为
B
派生自
Base2
,并不保证
B*
指针和
Base2*
指针都指向同一对象,将指向同一内存地址


如果您有一个
Base2*
指针,并且需要访问它的
B
数据,请使用
dynamic\u-cast
(或者
static\u-cast
,如果您确定对象是a
B
),以确保正确的
B*
指针。您可以从
B*
向下转换到
Base2*
,而不进行转换(这就是
B::bar的原因()
能够将
-a
B*
-传递到
a::foo()
当它需要一个
Base2*
作为输入时)。给定一个
B*
指针,您始终可以直接访问其
Base2
数据。

0x0045F0B8
是完整
B
对象的地址。
0x0045F0B9
B
对象的
Base2
子对象的地址

一般来说,完整对象的地址可能与基类子对象的地址不同。在您的情况下,
B
对象的布局可能如下所示:

+---+-------+
|   | Base1 | <-- 0x0045F0B8
| B |-------+
|   | Base2 | <-- 0x0045F0B9
+---+-------+
+---+-------+

|| Base1 |但是当我在codeingground编译这段代码时,输出的地址是相同的。你自己试试:@android927:这并不能保证在每个平台上的每个编译器中,甚至在同一个程序中的类似结构的类中。有人能解释一下为什么这被否决了吗?我认为这是一个合理的解释stion认为这种情况发生的原因目前还不明显,我相信很多人可以从这里发布的答案中获益。我可以提供一个部分解释:这个问题确实合理,甚至相当有趣。但是,一些用户对此并不感兴趣(如果您可以将这些特征归因于人类)。这里有很多讨厌的吹毛求疵的人认为他们是真正的热门编程天才。请不要把他们看得太重,因为大多数SO社区的用户都有积极的态度,他们愿意提供帮助。你得到我的+1,下面的两个答案也是如此。我有什么办法可以向B的实例询问其完整地址吗?我会的我想在a中有一个函数,比较两个B指针的地址,看看它们是否指向同一个实例,我在尝试实现它时遇到了这个问题。@android927
dynamic_cast(ptr)
@MattMcNabb不起作用,因为在我的例子中,ptr是一个指针,可以指向从Base2继承的各种类中的任何一个。如果我做了
动态转换(ptr),它会起作用吗
在我比较的两个指针上?@android927
dynamic\u cast
可能会起作用——它会给你完整对象的地址。但是你需要确保实际指向的是多态的(例如,通过确保你正在做的所有类都有虚拟析构函数)。为了可靠地比较两个指针,它们必须指向相同的数据类型,以确保对齐方式相同。只有这样,指向同一对象的两个指针才能正确对齐。您无法将a
B*
与a
Base1*
或a
Base2*
进行比较,但您可以将a
B*
与a
B*、a
Base1*
到a
Base1*
、a
Base2*
到a
Base2*
,等等。在本例中,如果将a
B*
与a
BaseX*
进行比较,编译器可能会在执行比较之前自动将
B*
向下转换为
BaseX*