как сохранить константную корректность во всех указателях?

StackOverflow https://stackoverflow.com//questions/21065391

  •  26-12-2019
  •  | 
  •  

Вопрос

Я пытаюсь выполнить операцию const над классом, который действительно является const - он не изменяет данные, на которые указывает класс.

Например:

class Node{
public:
    int val;
};
class V{
public:
    Node * node; //what is the change that is needed here?
    void const_action()const{
        node->val=5; //error wanted here
    }
    void action(){
        node->val=5; //error is not wanted here
    }
};
Это было полезно?

Решение

Вы можете использовать шаблон для обеспечения того, чтобы обеспечить правильность корректности Const по указателю без изменения значения или реализации вашего класса:

    template <typename T>
class PreseveConstPointer
{
    T *t_;
public:
    PreseveConstPointer(T *t = nullptr)
        : t_(t)
    {
    }
    PreseveConstPointer<T> * operator=(T *t)
    {
        t_ = t;
        return this;
    }
    T* operator->()
    {
        return t_;
    }
    T const * operator->() const
    {
        return t_;
    }
    T * data()
    {
        return t_;
    }
};
class Node{
public:
    int val;
};
class V{
public:
    PreseveConstPointer<Node> node;
    V()
    {
        node = new Node;
    }
    ~V()
    {
        if(node.data())
            delete node.data();
    }
    void const_action()const{
        node->val=5; // You will get an error here
    }
    void action(){
        node->val=5; // No error here
    }
};
.

Другие советы

const после объявления функции говорится, что функции не разрешается изменять какие-либо члены класса (кроме тех, которые помечены mutable).

Поскольку ваш код не изменяет ни одного члена класса, а изменяет только объект node указывает на то, что обе функции будут скомпилированы.

AFAIK, нет никакого способа предотвратить это.Если вы отметите node const, ни один из них не будет компилироваться.

Ты сбиваешь с толку Node* const для Node const*.

[Неудачный?] побочный эффект использования косвенности здесь заключается в том, что constпринадлежность элемента-указателя не имеет ничего общего с фактическим Node на котором вы работаете.

Если вам не нужно, чтобы этот элемент был указателем, то это приятно просто:

class V
{
public:
    Node node;

    void const_action() const
    {
        node.val = 5; // error here
    }

    void action()
    {
        node.val = 5; // no error here
    }
};

Однако, учитывая его название, я подозреваю, что жизнь не так проста, и вам, по сути, не повезло.

Лицензировано под: CC-BY-SA с атрибуция
Не связан с StackOverflow
scroll top