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
存放在哪里?我只是不知道它是如何调用谷歌的。
答案 0 :(得分:6)
基本上,这里发生的是未定义的行为。它没有特别的名字;很可能它被称为编程错误。班级A
的内存布局为:
int a;
B
的内存布局是:
int a;
int b;
因此,在您的情况下,您只为a
分配空间,但幸运的是,它后面的空间是空闲的(因此没有其他信息被覆盖)并且它没有在未分配的空间上边界(否则,尝试写入未分配的页面时可能会发生错误。所以b
存储在自由空间中。
简而言之:不依赖此代码工作!
答案 1 :(得分:2)
@anderas提供了一个很好的解释为什么行为未定义。
以下是该标准的相关条款(n4431,强调我的):
11 ......
如果类型“指向cv1 B的指针”的rvalue指向实际上是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'
}
答案 2 :(得分:1)
行为未定义。如果是指向a
的指针,则只能将B*
投射到B
。
不要这样做。
你甚至不能写A* a = new B;
后跟(dynamic_cast<B*>(a))->foo();
,因为这些类不是多态类型。
答案 3 :(得分:0)
您的代码将导致2个未定义的行为:
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();
}