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){coutB
源于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
,如果您确定对象是aB
),以确保正确的B*
指针。您可以从B*
向下转换到Base2*
,而不进行转换(这就是B::bar的原因()
能够将此
-aB*
-传递到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指针的地址,看看它们是否指向同一个实例,我在尝试实现它时遇到了这个问题。@android927dynamic_cast(ptr)
@MattMcNabb不起作用,因为在我的例子中,ptr是一个指针,可以指向从Base2继承的各种类中的任何一个。如果我做了动态转换(ptr),它会起作用吗
在我比较的两个指针上?@android927dynamic\u cast
可能会起作用——它会给你完整对象的地址。但是你需要确保实际指向的是多态的(例如,通过确保你正在做的所有类都有虚拟析构函数)。为了可靠地比较两个指针,它们必须指向相同的数据类型,以确保对齐方式相同。只有这样,指向同一对象的两个指针才能正确对齐。您无法将aB*
与aBase1*
或aBase2*
进行比较,但您可以将aB*
与aB*、aBase1*
到aBase1*
、aBase2*
到aBase2*
,等等。在本例中,如果将aB*
与aBaseX*
进行比较,编译器可能会在执行比较之前自动将B*
向下转换为BaseX*
。