c++ 中的 const 和没有 const 方法?

Posted

技术标签:

【中文标题】c++ 中的 const 和没有 const 方法?【英文标题】:const and no const methods in c++? 【发布时间】:2010-10-15 15:21:05 【问题描述】:

我有一个程序,它的许多类都有一些带有关键字 const 的运算符和方法,如下所示:

operator const char* () const;
operator char* ();
void Save(const char *name) const;
void Load(const char *name);

首先:方法声明末尾的const是什么意思?,和放在开头一样吗?

第二:为什么需要 const 版本和无 const 版本的 operator()?

提前致谢。

【问题讨论】:

【参考方案1】:

首先:方法声明末尾的const是什么意思?,和放在开头一样吗?

没有。末尾的const 意味着可以在声明为const 的对象上调用该方法。开头的const表示返回值为const

第二:为什么需要 const 版本和无 const 版本的 operator()?

非常量版本返回一个char*,它不是常量。通过修改 char*,您实际上可以修改对象(假设 char* 是对象的成员)。

由于 const 对象不允许这样做,因此对于 const 对象有 operator() 的重载,因此会返回 const char*,因此无法通过它修改对象。

【讨论】:

【参考方案2】:

'const' 告诉编译器这个方法不会改变任何成员变量——在 const 实例上调用这个方法是安全的。因此,可以在 const 实例上调用 Save,因为它不会更改该实例。另一方面,加载会改变实例,因此不能用于 const 实例。

operator() 的 const 版本传回一个 const 指针,保证传回的缓冲区不会改变。大概这是指向该类的实例变量的指针。对于非常量实例,另一个 operator() 传回一个非常量指针。它必须是指向某些内存的指针,即使写入也不会改变实例的内容。

另外,有时查找“可变”关键字。理解这一点将有助于您理解这种 const-correctness 的概念。

【讨论】:

【参考方案3】:

成员函数常量。这意味着该函数不能(*)修改您的任何成员变量。这就像在这个函数调用的所有成员变量前面放置一个 const。这对您的类的客户来说是一个很好的保证,也可能有助于编译器优化。

(*) - 另见关键字 mutable。

【讨论】:

【参考方案4】:

const 放在方法声明的末尾表示对象本身或thisconst,而不是返回类型。

出于复杂的原因,C++ 允许在 const 上重载方法。这里没有足够的空间来详细介绍。但这里有几个简短的。

有时,当从const 类型调用一个方法时,它的行为会有所不同,这是有价值的,或者说是绝对必要的。最直接的示例是,当您希望从 const 方法返回 const 值并从普通方法返回非常量值时。 this 是否为const 会极大地改变内部方法的绑定。以至于它本质上将成为两个不同的方法体。因此,将其分解为两种不同的方法是有意义的。

【讨论】:

【参考方案5】:

除了其他答案之外还有一个注意事项:您的示例中没有 operator()

operator const char* () const;
operator char* ();

是转换运算符,这意味着类的对象可以隐式转换为C风格的字符串,如

void f(const MyClass& x, MyClass& y) 
  const char* x_str = x;
  char* y_str = y;

operator() 的声明和用法,这意味着您可以使用类似于函数的类类型的对象,如下所示:

class MyClass 
public:
  const char* operator() (int x, int y) const;
  // ...
;

void g(const MyClass& obj) 
  const char* result = obj(3, 4);

【讨论】:

【参考方案6】:

如果您正在寻找有关 C++ 的优秀资源(包括正确使用 const 的提示),请尝试“Effective C++”。

一个有用的网站:JRiddel.org

在 C++ 中,当您通过将方法 const 放在方法签名之后声明方法时,您断言“此方法不会更改正在调用它的对象中的任何非mutable 实例变量。”

返回值之前的const(例如:operator const char*..." 中的常量)声明它只返回一个指向const char* 的变量指针。 (您可能无法更改char* 的内容,但您可以重新分配指针。)如果您写“const char* const ...”,它将是一个指向常量字符的常量指针。 (const 在星号之后)。

多个版本很有用,因此编译器可以理解这一点:

const char* my_const_var = <object_name>();
char* my_var = <object_name>();

克里斯

【讨论】:

【参考方案7】:

你应该参考“HIGH·INTEGRITY C++ CODING STANDARD MANUAL”了解何时建议对类成员使用const修饰符:

高完整性 CPP 规则 3.1.8:声明“const”任何不修改对象外部可见状态的类成员函数。 (QACPP 4211, 4214)

理由:尽管语言强制执行按位 const 正确性,但 const 正确性应该被认为是逻辑的,而不是按位的。如果客户端无法确定对象是否由于调用该函数而发生更改,则应将成员函数声明为 const。 'mutable' 关键字可用于声明可在 const 函数中修改的成员数据,这仅应在成员数据不影响对象的外部可见状态的情况下使用。

class C 
 
public: 
     const C& foo()  return * this;     // should be declared const 
     const int& getData()  return m_i;  // should be declared const 
     int bar() const  return m_mi;      // ok to declare const 
private: 
int m_i; 
mutable int m_mi; 
;

参考 Effective C++ Item 21;Industrial Strength C++ 7.13;

【讨论】:

【参考方案8】:

    开头的常量适用于返回值。最后的 const 适用于方法本身。当您将方法声明为“const”时,您表示您无意修改该方法中类的任何成员变量。编译器甚至会做一些基本的检查以确保该方法不会修改成员变量。返回值中的 const 防止调用者修改返回的值。当您返回指向类管理的数据的指针或引用时,这可能很有用。这样做通常是为了避免返回复杂数据的副本,这在运行时可能会很昂贵。

    您有两个不同的运算符的原因是“const”版本返回一个指向可能是类内部数据的 const 指针。如果类的实例是 const,那么您可能希望返回的数据也应该是 const。 “非常量”版本只是提供了一个方法,当调用者有一个类的非常量实例时,该方法返回一个可修改的返回值。

【讨论】:

以上是关于c++ 中的 const 和没有 const 方法?的主要内容,如果未能解决你的问题,请参考以下文章

有没有其他方法可以制作 const 版本的类?

C++ 中的 const 正确性

《挑战30天C++入门极限》入门教程:C++中的const限定修饰符

C#中的const形参

有啥方法可以使用在一个函数中定义的 const 变量可以被 C++ 中同一程序中的其他函数使用

将数组作为 C++ 中方法的 const 参数传递