这可能会导致无限循环吗?
Might this cause an infinite loop?
为了定义函数的第二个 const
版本,这样做是否保证安全?看起来它会像我想要的那样无限递归 return 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;
}
在这种情况下,编译器总是会选择函数的非 const 版本,甚至不会调用 const 版本。
否则编译器将无法编译,你正在破坏常量。
例如我快速修改了代码:
#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 函数。编译器不会让你那样做。
现在,我知道这是一个测试,但这样做你将永远无法摆脱递归,它将永远循环,而且你在每次调用时都会通过在堆上分配来泄漏内存,这两件事加在一起可以导致灾难。
不完全是:正如@Pete Becker 在评论中指出的那样,如果您调用了 const
版本,那么 将 递归:
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
版本以特定方式调用它。
来自斯科特迈尔斯 Effective C++ - Third Edition:
When const
and non-const
member functions have essentially identical implementation, code duplication can be avoided by having the non-const
version call the const
version
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
转换为return 的 const
-ness。这样做是安全的,因为要调用非 const
版本,您必须有一个非 const this
.
但是,如果您只是提供对成员的访问权限,则只需具备以下内容即可简单易读:
class TestAccess;
class Test
{
TestAccess& t;
public:
const TestAccess& getA() const { return t; }
TestAcess& getA() { return t; }
};
为了定义函数的第二个 const
版本,这样做是否保证安全?看起来它会像我想要的那样无限递归 return 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;
}
在这种情况下,编译器总是会选择函数的非 const 版本,甚至不会调用 const 版本。 否则编译器将无法编译,你正在破坏常量。 例如我快速修改了代码:
#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 函数。编译器不会让你那样做。
现在,我知道这是一个测试,但这样做你将永远无法摆脱递归,它将永远循环,而且你在每次调用时都会通过在堆上分配来泄漏内存,这两件事加在一起可以导致灾难。
不完全是:正如@Pete Becker 在评论中指出的那样,如果您调用了 const
版本,那么 将 递归:
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
版本以特定方式调用它。
来自斯科特迈尔斯 Effective C++ - Third Edition:
When
const
and non-const
member functions have essentially identical implementation, code duplication can be avoided by having the non-const
version call theconst
version
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
转换为return 的 const
-ness。这样做是安全的,因为要调用非 const
版本,您必须有一个非 const this
.
但是,如果您只是提供对成员的访问权限,则只需具备以下内容即可简单易读:
class TestAccess;
class Test
{
TestAccess& t;
public:
const TestAccess& getA() const { return t; }
TestAcess& getA() { return t; }
};