0

假设我有以下三个类:

class Animal {};

class Human : public Animal {};

class Dog : public Animal
{
public:
   void setOwner(Animal* owner) { this->owner = owner; }
private:
   Animal* owner;
};

为什么允许以下行为,究竟发生了什么?

Dog d;
Human h;

d.setOwner(&h); // ?

起初,我尝试像这样强制转换它d.setOwner(&(Animal)h),但编译器给了我一个警告,我遇到了一个运行时错误。

编辑:编译器给我的警告是“获取临时地址”。为什么会这样?

4

3 回答 3

1

没有类型转换,而是一个Human is-an Animal。因此,任何作用于 a 的接口Animal*都将接受 a Human*。这同样适用于Animal&Human&。当然,他们只看到Animal对象界面的一部分。

于 2012-12-01T10:30:28.190 回答
1

这里 d.setOwner((Animal)&h)

您尝试将指针类型转换为对象类型。你不能这样做。

转换为 Animal 类的正确方法是

d.setOwner((Animal*)&h)

但是你

d.setOwner(&h);

之所以有效,是因为如果需要,C++ 中的指针会自动转换为基类。不需要显式转换为 Animal*。

于 2012-12-01T10:32:18.630 回答
1

正如其他人指出的那样,无需将派生*转换为基础*

但没有人回答警告的问题。是的,创建了一个临时动物。而不是投射指针,而是将对象本身从人类所有者投射到动物。这导致从人类所有者创建一个临时动物。这个临时地址被传递给 set 函数。当 setter 返回临时 Human disappers 时,可怜的 Dogs 所有者指针无效。

所以总是阅读警告。如果您不理解它们,则认为它们是错误的。

另一个问题 - 避免构造函数元素和成员具有相同的名称,否则有一天你会很难学会这条规则。

于 2012-12-01T17:09:18.707 回答