如何强制调用 const 限定的函数重载

How to force a call to a const qualified function overload?

本文关键字:函数 重载 何强制 调用 const      更新时间:2023-10-16

我正在尝试在类中调用const函数,但存在具有相同名称的非const函数。

注意:我不能只改名。

class MyQuestion
{
 void fun()
 {
   cout<<"a"; 
 }
 void fun()const
 { 
   cout<<"b"; 
 }
 void call()
 {
   fun();//<how to call fun() const?
 }
};

选项 #1:

通过指向const限定类型的指针调用该函数:

void call()
{
    static_cast<const MyQuestion*>(this)->fun();
    //          ~~~~^
}

C++11:

void call()
{
    const auto* that = this;
    //~~^
    that->fun();
}

C++17:

void call()
{
    std::as_const(*this).fun();
    //   ~~~~~~~^
}

选项#2:

使调用函数成为限定const函数:

void call() const
//          ~~~~^
{
    fun();
}

演示

您必须在常量指针上调用该函数。为此,我建议创建一个局部指针变量:

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 指针的强制转换,而无需提及类名(它基本上是对推导类型的 const 指针的static_cast(:

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()

现场演示

我想为已经发布的优秀解决方案添加另一种可能的解决方案。

可以帮助编译器使用具有预期签名的函数指针选择正确的重载:

// 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 版本时。

载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;
}