C ++多态函数将void *
和其他指针类型作为参数:它被认为是不明确的吗?
我担心因为任何指针都可以转换为void*
,下面的第二个调用会在下面的程序中执行void bar(void*)
而不是我预期的void bar(int*)
吗?
我测试了我的g ++,它按预期运行(即int *不会被转换为void *)。但是,在C ++语言规范方面,任何人都可以评论/回答这个问题吗?
foo.h中:
class Foo {
public:
void bar(void *);
void bar(int *);
};
main.cpp中:
...
struct A *p1;
int *p2;
Foo foo;
...
foo.bar(p1);
foo.bar(p2);
此外,假设bar
现在是虚拟多态函数,将void*
参数作为第一种形式,将基本抽象类指针参数作为第二种形式。使用派生类指针作为参数的调用是执行第一个表单还是第二个表单?即派生类指针是否会被强制转换为其基本抽象类指针(因此第二个表单将处于运行状态),或者它将被强制转换为void *
(因此第一个表单将在运行中) bar()
?
答案 0 :(得分:4)
根据overload resolution rules (section Ranking of implicit conversion sequences),由于参数可以转换为函数的参数类型,在这种情况下,最好的可行函数是隐式转换更好的函数。
有关:
class Foo {
public:
void bar(void*);
void bar(int*);
};
// ...
Foo foo;
int* p2;
foo.bar(p2);
第一个是排名3(转化),第二个排名是1(完全匹配)。如果完全匹配,不需要转换,则优于转化,它会调用void bar(int*)
。
然而,在第二种情况下会变得更复杂:
class Foo {
public:
virtual void bar(void*);
virtual void bar(Foo*);
virtual ~Foo() = default;
};
class FooTwo : public Foo {};
// ...
Foo foo;
FooTwo footwo;
foo.bar(&footwo);
由于两者都是排名3(转换),因此遵循转化排名规则。并且由于两个转化具有相同的转换排名,因此转到扩展转化排名规则。扩展规则2规定:
将指向派生的指针转换为指向指针的转换优于指向派生指针转换为指向空的指针,将指针转换为空转换为void要优于指针转换来源于无效。
考虑到这一点,void bar(Foo*)
被认为是比void bar(void*)
更好的匹配,这意味着它将由foo.bar(&footwo);
选择。
有关后者的示例,请参阅here。