假设我有三个类 - Animal
,Cat
和Dog
,其中Cat
和Dog
是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
将参数更改为完全匹配会产生类似的错误,只是说它无法从类转换为同一类。
我已经成功调用了它们从超类继承的子类函数和成员,所以我知道这在逻辑上应该可行。我只是不知道这种语言想要让我弯曲逻辑的方式。
修改
解决方案恰好是:指针让每个人都感到困惑。
在我的例子中,我将“not-pointers”发送到需要指针的函数,我只是将其切换。现在它工作正常。
答案 0 :(得分:5)
当您动态分配新对象时,您将获得指向该对象的指针。所以你需要将它存储在如下的指针中:
Dog* spike = new Dog();
Cat* puss = new Cat();
然后,您可以为spike
类型的任何参数传递puss
或Animal*
,假设Dog
和Cat
确实从Animal
继承。这是C ++中多态性的基础:
类型为“指向 cv
D
的指针”的prvalue,其中D
是类类型,可以转换为“指向的指针的prvalue” cvB
“,其中B
是D
的基类(第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
}
经过测试和工作。