将子类传递给一个带有超类的函数

时间:2012-12-02 19:41:17

标签: c++ inheritance parameters subclass

假设我有三个类 - AnimalCatDog,其中CatDogAnimal的子类(这个听起来像第一次讲座,但这不是我承诺的功课,只是简化了真实的代码)

Dog* spike = new Dog(); 
Cat* puss = new Cat();   

int main(int argc, char** argv)
{
    function(spike, puss);
    return 0;
}

void function(Animal *pet, Animal *pet2)
{
   magic->andSoForth();
}

现在生成以下错误:

Cannot convert parameter 1 from 'Dog *' to 'Animal'
  No constructor could take the source type,
    or constructor overload resolution was ambiguous

将参数更改为完全匹配会产生类似的错误,只是说它无法从类转换为同一类。

我已经成功调用了它们从超类继承的子类函数和成员,所以我知道这在逻辑上应该可行。我只是不知道这种语言想要让我弯曲逻辑的方式。

修改

解决方案恰好是:指针让每个人都感到困惑。

  • 声明指针。
  • 将指针作为参数发送给不处理指针的函数。

在我的例子中,我将“not-pointers”发送到需要指针的函数,我只是将其切换。现在它工作正常。

5 个答案:

答案 0 :(得分:5)

当您动态分配新对象时,您将获得指向该对象的指针。所以你需要将它存储在如下的指针中:

Dog* spike = new Dog();
Cat* puss = new Cat();

然后,您可以为spike类型的任何参数传递pussAnimal*,假设DogCat确实从Animal继承。这是C ++中多态性的基础:

  

类型为“指向 cv D的指针”的prvalue,其中D是类类型,可以转换为“指向的指针的prvalue” cv B“,其中BD的基类(第10条)。

当然,你可以立即将它们存储为Animal*

Animal* spike = new Dog();
Animal* puss = new Cat();

别忘了delete他们。更好的是,根本不使用new

Dog spike;
Cat puss;
void function(const Animal&, const Animal&);
function(spike, puss);

答案 1 :(得分:3)

合理的假设您遇到的问题是指向非指针的指针,反之亦然。但是您的代码不是真正的代码,而您的错误消息显然是而不是真正的错误消息。所以这些都是猜测,特别是那些已经发布的答案,说“这就是它”(它可能是,但不一定,不确定性完全是你自己的错)。


编辑:OP发布此内容后10秒更改了问题代码。

代码仍然与声称的错误消息不一致。

我不会在这个问题发生变化时追逐这个问题。


现在,关于做什么...


请勿使用new

有经验的C ++程序员有时会以受控的方式使用new,并用适当的代码包装。不称职的C ++程序员经常使用new。但总的来说,你不需要它,而且它有问题,所以更好,因为默认不使用它。

然后,你的程序(你忽略了显示)看起来像这样:

#include <iostream>

struct Animal {};
struct Dog: Animal {};
struct Cat: Animal {};

void function(Animal const& pet1, Animal const& pet2 )
{
   //magicAndSoForth();
}

int main()
{
    Dog spike; 
    Cat puss;

    function( spike, puss );
}

答案 2 :(得分:0)

function的原型几乎肯定会说

void function(Animal pet1, Animal pet2);

或类似的东西。 (我知道你有一个原型,因为function出现在main之后。如果你没有向前宣布它,C ++会抱怨它根本找不到function,不是它采用了错误类型的args。)

问题是,你的真实function需要指点。由于main出现在真实function之前,因此它看不到。它只看到一个带有实际Animal的声明,因此它尝试使用它......但是失败了,因为Animal指针不是Animal。 (由于存在重载的可能性,与原型不同的真实function与C ++一样好。就编译器所知,function(Animal, Animal)存在于另一个翻译单元中,而您只是定义{{ 1}}。}

查看代码以了解function(Animal*, Animal*)的声明,然后说出

function

与实际功能的签名相匹配。

PS:如果您已包含所有相关声明,这将更容易理解。

PPS:更好的想法是将引用改为suggested by Alf。但是为了做到这一点,你必须首先修复原型不匹配(或使实际功能出现在使用它的代码之前)

答案 3 :(得分:-1)

嗯,你需要做的就是这个

Animal *spike = new Dog();
Animal *puss = new Cat();

基本上,所有指针定义必须是基类,并且可以使用派生类指针初始化它们。

答案 4 :(得分:-2)

这应该是它的样子。

Dog* spike = new Dog();
Cat* puss = new Cat();

function(*spike, *puss);

void function(Animal pet, Animal pet2)
{
   //magic
}

经过测试和工作。