8

假设我有三个类 - Animal,CatDog, whereCatDog是子类Animal(这听起来确实像第一堂课,但我保证这不是作业,只是简化真实代码)

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

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

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

编辑

解决方案恰好是:指针混淆了每个人。

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

在我的示例中,我将“非指针”发送到需要指针的函数,我只是切换了它。现在它工作正常。

4

5 回答 5

7

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

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

然后,您可以传递spikepuss类型的任何参数Animal*,假设Dog并且Cat确实继承自Animal. 这是 C++ 中多态的基础知识:

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

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

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

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

Dog spike;
Cat puss;
void function(const Animal&, const Animal&);
function(spike, puss);
于 2012-12-02T19:47:08.127 回答
5

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


编辑: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 );
}
于 2012-12-02T20:21:16.917 回答
1

你的原型function几乎可以肯定地说

void function(Animal pet1, Animal pet2);

或与此非常相似的东西。(我知道您有一个原型,因为它function出现在main.function

问题是,你的真实function需要指针。而且由于main出现在 real 之前function,它没有看到。它只看到一个接受实际Animals 的声明,因此它尝试使用它......但失败了,因为 Animal 指针不是 Animal。(由于重载的可能性,与原型的真正function不同之处在于 C++。据编译器所知,function(Animal, Animal)存在于另一个翻译单元中,您也只是在定义function(Animal*, Animal*)。)

查看您的代码以查找 的声明function,并说明

void function(Animal *pet1, Animal *pet2);

与实际函数的签名相匹配。

PS:如果您包含所有相关声明,这将更容易弄清楚。

PPS:如Alf所建议的,一个更好的主意是取而代之。但无论如何,为了做到这一点,您必须首先修复原型不匹配(或使真正的函数出现在使用它的代码之前)

于 2012-12-02T22:25:53.333 回答
-1

嗯,你需要做的是这个

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

基本上,您的所有指针定义都必须是基类,并且可以使用派生类指针进行初始化。

于 2012-12-02T19:45:48.970 回答
-4

这就是它应该的样子。

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

function(*spike, *puss);

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

测试和工作。

于 2012-12-02T20:57:24.380 回答