重载函数的调用 - 以继承的类作为参数 - 是模棱两可的
call of overloaded function -with inherited class as argument- is ambiguous
这个标题已经被使用了很多次,但在搜索了大约 5-6 个示例后,我找不到任何符合我的问题:
我有一个简单的继承实践。
类 A 是一个基类,类 B 和 C 继承自它:
class A {
};
class B : public A { public: int i; };
class C : public A { public: int j; };
还有一个包含重载函数的 P 类,如下所示:
class P
{
public:
void change(B *b)
{
b->i =1;
}
void change(C *c)
{
c->j =1;
}
};
当我使用如下函数时:
int main()
{
A *b = new B();
A *c = new C();
P p;
p.change(b);
p.change(c);
return 0;
}
它给出一个错误说:
inherit2.cpp: In function ‘int main()’:
inherit2.cpp:37:12: error: call of overloaded ‘change(A*&)’ is ambiguous
inherit2.cpp:37:12: note: candidates are:
inherit2.cpp:21:7: note: void P::change(B*) <near match>
inherit2.cpp:21:7: note: no known conversion for argument 1 from ‘A*’ to ‘B*’
inherit2.cpp:26:7: note: void P::change(C*) <near match>
inherit2.cpp:26:7: note: no known conversion for argument 1 from ‘A*’ to ‘C*’
inherit2.cpp:38:12: error: call of overloaded ‘change(A*&)’ is ambiguous
inherit2.cpp:38:12: note: candidates are:
inherit2.cpp:21:7: note: void P::change(B*) <near match>
inherit2.cpp:21:7: note: no known conversion for argument 1 from ‘A*’ to ‘B*’
inherit2.cpp:26:7: note: void P::change(C*) <near match>
inherit2.cpp:26:7: note: no known conversion for argument 1 from ‘A*’ to ‘C*’
如果您能帮我解决问题,我将不胜感激。Rahman
Polymorphism is one answer
class A
{
public:
virtual void set() = 0;
};
class B : public A
{
public:
virtual void set() { i = 1; }
private:
int i;
};
class C : public A
{
public:
virtual void set() { j = 1; }
private:
int j;
};
class P
{
public:
void change(A *a)
{
a->set();
}
};
int main()
{
A *b = new B();
A *c = new C();
P p;
p.change(b);
p.change(c);
return 0;
}
使用多态性,不需要多种change
方法。
你可以:
-
通过为
i
和j
添加虚拟二传函数来使用多态性:class A { public: virtual void set( int ) = 0; }; class B : public A { public: void set( int value ) { i = value; } private: int i; }; class C : public A { public: void set( int value ) { j = value; } private: int j; }; class P { public: void change(A * obj) { obj->set(1); } }; int main() { A *b = new B(); A *c = new C(); P p; p.change(b); p.change(c); return 0; }
在 传递指针之前将其大小写:
A *b = new B(); A *c = new C(); P p; p.change(static_cast<B*>(b)); p.change(static_cast<C*>(c));
将变量放入基类中(并删除两个
change()
函数):class A { public: int i; }; class B : public A {}; class C : public A {};
我会调整你的类层次结构以使用多态性:
class A
{
public:
virtual void SetVariable(const int value) = 0;
};
class B : public A
{
public:
virtual void SetVariable(const int value) override { i = value; }
int i;
};
class C : public A
{
public:
virtual void SetVariable(const int value) override { j = value; }
int j;
};
class P
{
public:
void change(A *a)
{
a->SetVariable(1);
}
};
这样,您可以使用指向基类(A
)的指针,而不知道它们是哪个特定的派生类型。
根本原因:
当你调用change()
你传递的参数是类型A *
时,这个函数在类P
中没有完全匹配。编译器尝试找到最佳匹配项,它有两个选择:
void change(B *);
void change(C *);
它们都不是最佳匹配,因为每个都需要从 A*
转换为 B*
或 C*
.并不是说您的类不提供此转换函数,因此编译器会报告错误。
分辨率:
通过使用强制转换,准确告诉编译器要选择哪个版本的函数。
p.change(static_cast<B*>(b));
p.change(static_cast<C*>(c));
在上述两种情况下,您都知道A *
所指向的对象的实际类型,因此您可以使用static_cast
并指导编译器找到最佳匹配函数。
相关文章:
- 如何反转整数参数包
- 使用C++库在Android项目中修改gradle中的cmake参数,用于插入指令的测试
- 如何使用默认参数等选择模板专业化
- 模板参数替换失败,并且未完成隐式转换
- 具有默认模板参数的多态类的模板推导失败
- lambda参数转换为constexpr技巧,然后获取带链接的数组
- 将数组作为参数传递给函数安全吗?作为第三方职能部门,可以探索他们想要的之外的其他元素
- 函数调用中参数的顺序重要吗
- 部分定义/别名模板模板参数
- 模板-模板参数推导:三个不同的编译器三种不同的行为
- 使用不带参数的函数访问结构元素
- 基于另一个成员参数将函数调用从类传递给它的一个成员
- 如何在OMNET++中指定与命令行参数组合的输出文件名
- 如何使用Luacneneneba API正确读取字符串和表参数
- 在派生函数中指定void*参数
- 如何处理模棱两可的模板参数
- variadic形式对单个参数的非variadic形式是模棱两可的
- 重载函数的调用 - 以继承的类作为参数 - 是模棱两可的
- C++ 多态函数以 void * 和其他指针类型为参数:是否被认为是模棱两可的
- 为什么即使给出了模板参数,ptr_fun也会发现这是模棱两可的?