对于C++新手来说,允许const成员函数在类引用的对象(通过指针或引用)上调用非const方法通常会让人感到困惑.例如,以下内容完全正确:
class SomeClass
{
class SomeClassImpl;
SomeClassImpl * impl_; // PImpl idiom
public:
void const_method() const;
};
struct SomeClass::SomeClassImpl
{
void non_const_method() { /*modify data*/ }
};
void SomeClass::const_method() const
{
impl_->non_const_method(); //ok because impl_ is const, not *impl_
};
Run Code Online (Sandbox Code Playgroud)
但是,如果constness传播到尖头对象,它有时会非常方便(我自愿使用PImpl习语,因为它是我认为"constness传播"非常有用的情况之一).
使用指针时,可以通过使用某种智能指针轻松实现这一点,操作符在constness上重载:
template < typename T >
class const_propagating_ptr
{
public:
const_propagating_ptr( T * ptr ) : ptr_( ptr ) {}
T & operator*() { return *ptr_; }
T const & operator*() const { return *ptr_; }
T * operator->() …Run Code Online (Sandbox Code Playgroud) 我试图const更深入地理解c ++的语义,但我无法完全理解constness保证值得的是什么.正如我所看到的,constness保证不会有变异,但请考虑以下(人为的)示例:
#include <iostream>
#include <optional>
#include <memory>
class A {
public:
int i{0};
void foo() {
i = 42;
};
};
class B {
public:
A *a1;
A a2;
B() {
a1 = &a2;
}
void bar() const {
a1->foo();
}
};
int main() {
B b;
std::cout << b.a2.i << std::endl; // output is 0
b.bar();
std::cout << b.a2.i << std::endl; // output is 42
}
Run Code Online (Sandbox Code Playgroud)
因为bar就是const,人们会认为它不会发生变异对象b.但是在它的调用b发生变异之后.如果我写的方法foo …