有人可以解释我为什么在使用此指针和&运算符时在基地址和派生对象的地址上有所不同。下面是我的代码
#include <iostream>
using namespace std;
class A
{
public:
A()
{
cout<<"Base Address "<<this<<endl;
}
};
class B:public A
{
public:
B()
{
cout<<"Deri Address "<<this<<endl;
}
};
int main()
{
B b;
}
The O/P is
Base Address 0x7fff500e9bdf
Deri Address 0x7fff500e9bdf
两者都一样。
当我在主体中添加另外两个语句时,如下所示
#include <iostream>
使用命名空间标准;
class A
{
public:
A()
{
cout<<"Base Address "<<this<<endl;
}
};
class B:public A
{
public:
B()
{
cout<<"Deri Address "<<this<<endl;
}
};
int main()
{
B b;
A a;
cout<<&a<<endl<<&b<<endl;
}
O / P如下所示
Base Address 0x7fff82c696df
Deri Address 0x7fff82c696df
Base Address 0x7fff82c696de
0x7fff82c696de
0x7fff82c696df
现在我可以清楚地看到地址不同
a)造成这种差异的原因可能是什么
b)我想知道的一件事是派生类中的基础子对象是否与基础对象完全相同?我对此感到困惑,因为如果我们在基类中说是否有变量x,并且如果我们有该基类的派生类(非多态情况),那么现在如果我们讨论派生中的基子对象,是否基类中存在的相同x也存在于派生类的基础子对象中(我的意思是变量在派生基类和基础子对象中具有相同的地址),或者我们在基类和基础子对象中都有x的单独副本的(我的意思是具有不同地址的变量)
Please clarify?
答案 0 :(得分:1)
您有两个对象: a 和 b :
地址为0x7fff82c696de的a
b地址为0x7fff82c696df
答案 1 :(得分:1)
为什么您得到所看到的?那是因为a != b
您确实创建了2个对象:
A a;
B b;
它清除是否在类A的构造函数中添加另一个参数
class A
{
public:
A(std::string name)
{
cout<<name<<"'s Base Address "<<this<<endl;
}
};
并稍微修改您的main
函数
int main()
{
B b("b");
A a("a");
cout<<"a: "<<&a<<endl<<"b: "<<&b<<endl;
}
现在您的输出将如下所示
b's Base Address 0x7fff82c696df
b's Deri Address 0x7fff82c696df
a's Base Address 0x7fff82c696de
a: 0x7fff82c696de
b: 0x7fff82c696df
现在您可以看到& operator
和*this
的结果相等。您只需要拖曳带有两个不同地址的不同对象。
您还会看到,对于派生类B
,this
在B
和A
的构造函数中具有相同的值。
答案 2 :(得分:0)
我想为您澄清的第一件事是理解 class 与 object 之间的区别。 类是一个蓝图,而对象是该类的一个实例。
因此,如果您不创建该类的实例,那么您的存储器将一无所有。
在第一种情况下,打印的地址是相同的,因为您创建了一个实例。因为只有一个对象,所以拥有相同的地址是很有意义的。
在第二种情况下,地址不同是因为有两个不同的对象(创建了类的两个实例),而不是因为使用了&
。因此,以下代码将打印相同的地址。
#include <iostream>
class A
{
public:
A() { std::cout << "Address with this pointer: " << this << std::endl; }
};
int main()
{
A a;
std::cout << "Address with & operator: " << &a << std::endl;
}
编辑:为什么代表子对象相同的地址
正如我在评论中提到的那样,我从未听过 sub-object 一词。但是我从here得到了下面的定义。
子对象:存储在另一个对象(数组元素,基类对象和数据成员对象)中的任何对象。
一个对象自然会占据一个内存,并且该对象的任何子对象都需要位于该内存中的某个位置。
第一个创建的子对象(按照定义的顺序)获取内存的第一部分,第二个创建的子对象获取紧随其后的内存的第二部分第一个对象,依此类推。
因此,第一个创建的子对象与对象本身具有相同的起始地址。在下面的代码中,第一个创建的对象是 Class A 的实例(因此A和C具有相同的地址),这是因为 Class A 继承于 Class B 。如果将class C : public A, public B
更改为class C : public B, public A
,则B类和C类的对象将是相同的。
#include <iostream>
class A
{
public:
A() { std::cout << "Address of Sub-Object A: " << this << std::endl; }
int x;
};
class B
{
public:
B() { std::cout << "Address of Sub-Object B: " << this << std::endl; }
int y;
};
class C : public A, public B {
public:
C() : A() , B() { std::cout << "Address of Object C: " << this << std::endl; }
int z;
};
int main()
{
C c;
}
PS::如果您考虑组成而不是继承,那么它可能更易于理解。