以 void * 和其他指针类型为参数的 C++ 多态函数:它是否被认为是有歧义的?
C++ polymorphism function taking void * and other pointer type as argument: is it considered ambiguous?
以 void *
和其他指针类型作为参数的 C++ 多态函数:它是否被认为是不明确的?
我担心,因为任何指针都可以转换为 void*
,下面程序中的第二次调用 bar 会执行 void bar(void*)
而不是我预期的 void bar(int*)
吗?
我在我的 g++ 上进行了测试,它按预期运行(即 int* 不会转换为 void*)。但是任何人都可以 comment/answer on/to 这个关于 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*
参数作为第一种形式,将基本抽象 class 指针参数作为第二种形式。使用派生的 class 指针作为参数的调用会执行第一种形式还是第二种形式?即派生的 class 指针会被转换为它的基本抽象 class 指针(因此第二种形式将起作用),还是会被转换为 void *
(因此第一种表单将在调用 bar()
?
之前生效)
根据 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 状态:
Conversion that converts pointer-to-derived to pointer-to-base is better than the conversion of pointer-to-derived to pointer-to-void, and conversion of pointer-to-base to void is better than pointer-to-derived to void.
考虑到这一点,void bar(Foo*)
被认为比 void bar(void*)
更匹配,这意味着它会被 foo.bar(&footwo);
选中。
有关后者的示例,请参阅 here。
以 void *
和其他指针类型作为参数的 C++ 多态函数:它是否被认为是不明确的?
我担心,因为任何指针都可以转换为 void*
,下面程序中的第二次调用 bar 会执行 void bar(void*)
而不是我预期的 void bar(int*)
吗?
我在我的 g++ 上进行了测试,它按预期运行(即 int* 不会转换为 void*)。但是任何人都可以 comment/answer on/to 这个关于 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*
参数作为第一种形式,将基本抽象 class 指针参数作为第二种形式。使用派生的 class 指针作为参数的调用会执行第一种形式还是第二种形式?即派生的 class 指针会被转换为它的基本抽象 class 指针(因此第二种形式将起作用),还是会被转换为 void *
(因此第一种表单将在调用 bar()
?
根据 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 状态:
Conversion that converts pointer-to-derived to pointer-to-base is better than the conversion of pointer-to-derived to pointer-to-void, and conversion of pointer-to-base to void is better than pointer-to-derived to void.
考虑到这一点,void bar(Foo*)
被认为比 void bar(void*)
更匹配,这意味着它会被 foo.bar(&footwo);
选中。
有关后者的示例,请参阅 here。