Как принудительно вызвать перегрузку функции с константой?
Я пытаюсь вызвать функцию const
внутри класса, но существует функция non const
с тем же именем.
Примечание. Я не могу просто изменить имена.
class MyQuestion
{
void fun()
{
cout<<"a";
}
void fun()const
{
cout<<"b";
}
void call()
{
fun();//<how to call fun() const?
}
};
Ответы
Ответ 1
Вариант №1:
Вызвать эту функцию с помощью указателя на const
квалифицированный тип:
void call()
{
static_cast<const MyQuestion*>(this)->fun();
// ~~~~^
}
Вариант № 2:
Сделать вызывающую функцию a const
-qualified одним:
void call() const
// ~~~~^
{
fun();
}
Ответ 2
Вы должны вызвать функцию на указателе const. Для этого я рекомендую создать локальную переменную-указатель:
const auto *c = this;
c->fun(); // calls fun() const
fun(); // calls fun()
Живая демонстрация
Если вам это нужно часто и/или если вы не хотите использовать локальную переменную, вы также можете ввести частную вспомогательную функцию, которая возвращает const this указатель:
const MyQuestion *const_this() const {
return this;
}
а затем вызовите fun
следующим образом:
const_this()->fun(); // calls fun() const
fun(); // calls fun()
Демо-версия
Еще один вариант - написать функцию make_const
, которая выполняет приведение к указателю const без необходимости упоминать имя класса (это в основном a static_cast
для указателя const выведенного типа):
template <typename T>
const T* make_const(T *ptr) {
return ptr;
}
а затем вызовите fun
следующим образом:
make_const(this)->fun(); // calls fun() const
fun(); // calls fun()
Демо-версия
Для аргумента (я не рекомендую следующий), в сочетании с предложением выше, вы также можете ввести глобальный макрос, который расширяется до make_const(this)
:
#define const_this make_const(this)
а затем вызовите fun
следующим образом:
const_this->fun(); // calls fun() const
fun(); // calls fun()
Живая демонстрация
Ответ 3
Я хотел бы добавить еще одно возможное решение для уже отличных.
Вы можете помочь компилятору выбрать правильную перегрузку с помощью указателя функции с ожидаемой сигнатурой:
// Pointer to the version of fun with const
void (MyQuestion::*f)()const = &MyQuestion::fun;
(this->*f)(); // This would call the const fun
Смотрите демо здесь или полный код ниже:
struct MyQuestion
{
void fun()
{
std::cout<<"a";
}
void fun()const
{
std::cout<<"b";
}
void call()
{
void (MyQuestion::*f)()const = &MyQuestion::fun;
(this->*f)();
}
};
Почему это работает?
Ну, тип указателя f
равен void (MyQuestion::*)()const
, который совпадает с MyQuestion::foo()const
, но не совпадает с MyQuestion::foo()
, поэтому, когда вы берете адрес электронной почты функции &MyQuestion::fun
, указатель f
> может указывать только на версию const.
Ответ 4
как насчет перегрузки call(). Следующее выполнение выполняет эту работу. Я предполагаю, что это то, что вы хотите реализовать.
#include <iostream>
using namespace std;
class A
{
public:
void fun() { cout << "non" << endl; }
void fun() const { cout << "const" << endl; }
void call() { fun(); }
void call() const { fun(); }
};
int main()
{
A a;
a.call();
const A b;
b.call();
return 0;
}