2012-12-01 89 views
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),但是编译器给了我一个警告,我打了一个运行时错误。

编辑:编译器给我的警告是“以暂时的地址”。这是为什么?

回答

1

这里 d.setOwner((动物)& 1H)

你尝试下的指针类型对象类型。你不能这样做。

铸造动物类的正确方法是

d.setOwner((Animal*)&h) 

但你

d.setOwner(&h); 

使用,因为在C指针,如果需要++被自动转换为一个基类。显式转换为Animal *不是必需的。

1

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

1

当别人pionted了没有必要投下衍生*立足*

,但没有人answerd问题的警告。 是的,有一个临时动物创建。而不是铸造指针,将对象本身从人类所有者转移到动物。这导致了人类所有者创造了一个临时动物。这个临时地址被传递给设置的功能。当二传手回归临时人类消沉者时,可怜的狗主人指针是无效的。

所以总是读警告。如果你不明白他们认为他们是错误的。

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