class A
{
public:
int a;
};
class B:public A
{
public:
int b;
void foo()
{
b=a*a;
}
};
int _tmain(int argc, _TCHAR* argv[])
{
A * a=new A;
a->a=10;
((B*)a)->foo();
cout<<((B*)a)->b;
}
这是工作的b=100
,但我不知道它的工作规则。b
存储在哪里?我只是不知道怎么叫谷歌
基本上,这里发生的是未定义行为。它没有特殊的名字;它很可能被称为编程错误。你的类A
的内存布局是:
int a;
B
的内存布局为:
int a;
int b;
因此,在您的示例中,您只为a
分配空间,但是您很幸运,它之后的空间是空闲的(这样就不会覆盖其他信息),并且它不会覆盖未分配的空间(否则,在尝试向未分配的页面写入时可能会发生错误)。因此,b
存储在空闲空间中。
行为未定义。只有当是指向B
的指针时,才能将a
转换为B*
。
不要这样做。
你甚至不能写A* a = new B;
后面跟着(dynamic_cast<B*>(a))->foo();
,因为类不是多态类型
@anderas提供了一个很好的解释为什么行为是未定义的。
这是标准(n4431,重点是我的)中的一个相关条款:
11……
如果"指向cv1 B的指针"类型的右值指向实际上是D类型对象的子对象的B,则结果指针指向D类型的封闭对象。否则,强制转换的结果是未定义的
[expr.static.cast]
因此,代码中的强制转换是未定义的。
可以这样写:
class A
{
public:
int a;
virtual void foo() = 0; // make it polymorphic
};
class B:public A
{
public:
int b;
virtual void foo()
{
b=a*a;
}
};
int _tmain(int argc, _TCHAR* argv[])
{
A * a=new B; // create an instance of B
a->a=10;
((B*)a)->foo();
cout<<((B*)a)->b;
// don't forget to delete 'a'
}
你的代码将导致两个未定义的行为:
- 当你将
A
的实例转换为B
时。 - 当您使用成员变量
b
时(该变量不存在)在内存中)。
下面是使用B的实例作为a的指针的潜在实现
class A
{
public:
void setA(int aToSet)
{
a = aToSet;
}
virtual void foo() = 0;
virtual void getResult() const = 0;
private:
int a;
};
class B : public A
{
public:
void foo() override
{
b = a * a;
}
void getResult() const override
{
return b;
}
private:
int b;
};
int _tmain(int argc, _TCHAR* argv[])
{
A *a = new B();
a->setA(10);
a->foo();
cout << a->getResult();
}