Я нарушаю const-правильность, если я выставляю const и неконстантный API? - PullRequest
2 голосов
/ 12 октября 2019

Я разрабатываю класс, и у меня были некоторые опасения по поводу правильности, но я не думаю, что у меня есть полное понимание того, что на самом деле означает это понятие. Если я сохраню необработанный указатель на неконстантный тип и захочу предоставить константные и неконстантные методы доступа к этому указателю, нарушит ли это константность? Тип

class A
{
public:
    void SetCount(int* pCount)
    {
        m_pCount = pCount;
    }

    void GetCount(const int** ppCount) const
    {
        *ppCount = m_pCount;
    }

    void GetCount(int** ppCount) const
    {
        *ppCount = m_pCount;
    }

private:
    int* m_pCount = nullptr;
};

int main()
{
    int count = 10;

    A a;
    a.SetCount(&count);

    const int* pCountConst = nullptr;
    a.GetCount(&pCountConst);

    // Prints 10.
    std::cout << *pCountConst << std::endl;

    int* pCountNonConst = nullptr;
    a.GetCount(&pCountNonConst);
    (*pCountNonConst)++;

    // Prints 11.
    std::cout << *pCountConst << std::endl;
}

pCount равен const int*, поэтому мы ожидаем, что базовый int никогда не изменится после инициализации. Мне кажется, что мы нарушаем здесь константность, это правда?

1 Ответ

2 голосов
/ 12 октября 2019

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

Если вы хотите, чтобы от A до была эта переменная подсчета, вам, вероятно, следует сохранить const -ness при доступе к ней. В этом случае вы можете написать свои функции следующим образом:

void GetCount(const int** ppCount) const
{
    *ppCount = m_pCount;
}

void GetCount(int** ppCount) // note - omitted const
{
    *ppCount = m_pCount;
}

Это означает, что если у вас есть не const A, вы можете получить неконстантный счетчик, но если у вас естьconst A вы можете получить только счетчик const.


Вы также можете иметь в виду, что A просто наблюдает некоторую переменную count. В этом контексте наблюдатель const означает, что вы не будете менять то, на что указываете, но сама эта вещь может измениться. В этом случае вы могли бы написать свой аксессор следующим образом:

void GetCount(int** ppCount) const
{
    *ppCount = m_pCount;
}

В общем, я бы сказал, что предпочел бы первый метод и сохранить const -ность, но другой способ, безусловно, действителен вопределенные обстоятельства.

...