1
class A
{
public:
    A(){ val = 0; p = new int; *p = 0; }
    //void fun_1()const{ val = 1; }  not allowed
    void fun_2()const{ *p = 1; }
    void display()const{ cout<< val <<' '<< *p <<endl; }
private:
    int val;
    int * p;
};

int main()
{
    const A a;
    a.fun_2();
}

fun_1()const不允许更改 const 成员函数中的成员数据。但是,当数据不是直接属于对象的成员,而是在对象内部分配存储和赋值时,const 函数无法保护它。fun_2()const例如,虽然它是一个 const 函数,但可以更改p指向的数据。

有没有办法保护p指向的数据?

4

4 回答 4

3

让编译器保护指向的对象相对简单,但这不是自动完成的,因为它并不总是正确的做法。

template<typename T>
class constinator_ptr
{
    T* p;
public:
    explicit constinator_ptr( T* p_init ) : p (p_init) {}

    T*& ptr() { return p; } // use this to reassign, or also define operator=(T*)

    T* operator->() { return p; }
    const T* operator->() const { return p; }
    T& operator*() { return *p; }
    const T& operator*() const { return *p; }
};

只需使用它来代替原始指针,如下所示:

class A
{
public:
    A() : val{0}, p{new int(0)} {}
    //void fun_1()const{ val = 1; }  not allowed
    void fun_2()const{ *p = 1; } // now causes error
    void display()const{ cout<< val <<' '<< *p <<endl; }
private:
    int val;
    constinator_ptr<int> p;
};
于 2013-10-06T15:58:23.893 回答
2

只需编写您的成员函数,以便它们不允许调用者修改对象。只要指针是私有的,它指向的任何东西都只能被其他成员函数看到。如果您不公开更改指向对象的成员函数,则您的类的用户无法更改它。

请注意,您可以将成员声明为“指向 const 的指针”(与 const 指针不同)。

int const* p是指向 const int 的指针(指针可以更改,但它指向的 int 不能),而int* const是指向 int 的 const 指针(指针不能更改——它总是指向同一个 int,但值该 int 可以更改)。当然,aint const* const是一个指向 const int 的 const 指针。指针和 int 都不能修改。

但是,这并不能真正帮助您强制执行“const 成员函数不应修改指向的对象,但 non-const 成员函数可以”(因为指向 const int 的指针将始终指向 const int,即使如果从非常量成员函数中使用)

于 2013-10-06T15:35:14.547 回答
2

只需声明一个指向常量的指针:

const int * p;


void fun_2()const{ *p = 1; } // main.cpp:36: error: assignment of read-only  
                                // location ‘*(const int*)((const B*)this)->B::p’

在这种情况下, 所指向的整数p 根本无法更改,无论是从函数体const还是non-const函数体中完成。如果您仍然希望能够从non-const成员函数更改 int 的值,则不得在类外部公开指针,将指针设为私有并相应地使用它。

于 2013-10-06T15:39:26.523 回答
2

一个简单而通用的解决方案是您自己的具有深度常量语义的智能指针类。只需在 中包装一个普通指针deepconst<T>,将const T* operator->() const和添加const T& operator*() const到通常的非常量版本,就可以了。

于 2013-10-06T15:54:27.970 回答