перегрузка — функция полиморфизма C ++, принимающая void * и другой тип указателя в качестве аргумента: считается ли это неоднозначным?

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* аргумент в качестве 1-й формы, и указатель на базовый абстрактный класс в качестве 2-й формы. Будет ли вызов с указателем производного класса в качестве аргумента выполнять первую или вторую форму? будет ли приведен указатель производного класса к его базовому указателю абстрактного класса (и, таким образом, будет действовать вторая форма), или он будет приведен к void * (и, таким образом, первая форма будет в действии) перед вызовом bar()?

0

Решение

В соответствии с правила разрешения перегрузки (раздел Ранжирование неявных конверсионных последовательностей), поскольку аргумент может быть преобразован в тип параметра любой функции, лучшей жизнеспособной функцией в этом случае будет та, у которой неявное преобразование лучше.

За:

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);,

Увидеть Вот для примера последнего.

4

Другие решения

Других решений пока нет …

По вопросам рекламы [email protected]