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
放在方法声明的末尾表示对象本身或this
是const
,而不是返回类型。
出于复杂的原因,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 方法?的主要内容,如果未能解决你的问题,请参考以下文章
《挑战30天C++入门极限》入门教程:C++中的const限定修饰符