const 成员函数是否调用非 const 版本,还是递归的?

问题描述 投票:0回答:2

对于定义函数的第二个

const
版本,这样做是否能保证安全?看起来它会有无限递归,因为我想返回
const
但我要调用的另一个函数是非常量的。

它可以与 g++ 一起使用,但我担心这不安全。

#include <iostream>

using namespace std;

class test {
public:
   int* doSomething(int a) {
      int* someInt = new int(a);

      return someInt;
   }

   const int* doSomething(int a) const {
      return doSomething(a);
   }
};

int main() {
   test a;

   cout << *a.doSomething(12345) << endl;

   return 1;
}
c++ recursion constants const-correctness function-qualifier
2个回答
3
投票

不完全是:正如 @Pete Becker 在评论中指出的那样,如果您调用了

const
版本,那么 will 会递归:

class test {
public:
   int* doSomething(int a) {
      int* someInt = new int;
      *someInt = a;
      return someInt;
   }

   const int* doSomething(int a) const {
      return doSomething(a);
   }
};

int main() {
   const test a;
   // You're not in for a good time:
   a.doSomething(12345);
   return 1;
}

当提供需要重复代码的函数的

const
和非
const
版本时,最好实现
const
版本,然后让非
const
版本以特定方式调用它。

来自 Scott Myers Effective C++ - 第三版

const
和非
const
成员函数具有基本相同的实现时,可以通过让非
const
版本调用
const
版本来避免代码重复

Scott Myers 继续提供了一种安全的方法来做到这一点:

const int* doSomething(int a) const
{
   int* someInt = new int;
   *someInt = a;
   return someInt;
}

int* doSomething(int a)
{
   return const_cast<int*>(static_cast<const Test&>(*this).doSomething());
}

在非

const
版本中,有两种强制转换:
static_cast
基本上将
this
变成
const this
,其中
const_cast
抛弃了返回的
const
性。这样做是安全的,因为要调用非
const
版本,您必须拥有非
const this

但是,如果您只是向成员提供访问权限,则仅具有以下内容就更简单且更容易阅读:

class TestAccess;
class Test
{
    TestAccess& t;
public:
    const TestAccess& getA() const { return t; }
    TestAcess& getA() { return t; }
};

0
投票

在这种情况下,编译器总是会选择函数的非 const 版本,甚至不会调用 const 版本。 否则编译器将无法编译,您正在制动 constens。 例如我快速修改了代码:

#include <iostream>

using namespace std;

class test {
public:
    int* doSomething(int a) {
        int* someInt = new int;

        *someInt = a;
        return someInt;
    }
    int ax = 10;
    void somethingElse(int i)
    {
        ax = i;
    }
    const int* doSomething(int a) const {
        somethingElse(a);
        return 0;
    }
};

int main() {
    test a;

    cout << *a.doSomething(12345) << endl;

    return 1;
}

此示例无法编译,因为您正在 const 作用域内调用 const 函数。编译器不会让你这样做。

现在,我知道这是一个测试,但这样做你将永远不会退出递归,它将永远循环,而且你每次调用时都会通过在堆上分配来泄漏内存,这两件事加在一起可能会导致灾难.

© www.soinside.com 2019 - 2024. All rights reserved.