Вызов неконстантной функции-члена из константной функции-члена - PullRequest
14 голосов
/ 29 октября 2010

Я хотел бы знать, возможно ли вызвать неконстантную функцию-член из константной функции-члена. В приведенном ниже примере First дает ошибку компилятора. Я понимаю, почему это дает ошибку, я хотел бы знать, есть ли способ обойти это.

class Foo
{
   const int& First() const
   {
         return Second();
   }

   int& Second()
   {
        return m_bar;
   }

   int m_bar;
}

Я действительно не хочу обсуждать мудрость этого, мне любопытно, возможно ли это вообще.

Ответы [ 7 ]

31 голосов
/ 29 октября 2010
return (const_cast<Foo*>(this))->Second();

Тогда плачь, тихо.

10 голосов
/ 29 октября 2010

Это возможно :

const int& First() const 
{ 
    return const_cast<Foo*>(this)->Second(); 
}

int& Second() { return m_bar; }

Я бы не рекомендовал это;это уродливо и опасно (любое использование const_cast опасно).

Лучше перенести столько общих функций, сколько вы можете, в вспомогательные функции, тогда пусть ваши константные и неконстантные функции-члены будут выполнять как можно меньшеработать так, как им нужно.

В случае простого средства доступа, подобного этому, return m_bar; из обеих функций столь же легко, как и для вызова одной функции из другой.

3 голосов
/ 13 февраля 2014

Ограничение методов-членов const пришло во время компиляции. Если вы можете обмануть компилятор, тогда да.

class CFoo
{ 
public:
    CFoo() {m_Foo = this;}
    void tee();

    void bar() const 
    { 
        m_Foo->m_val++;  // fine 
        m_Foo->tee();    // fine
    }
private:
   CFoo * m_Foo;
   int    m_Val;  

};

Это фактически отменяет назначение функции-члена const, поэтому лучше этого не делать при разработке нового класса. Не вредно знать, что есть способ сделать это, особенно его можно использовать в качестве обходного пути для этого старого класса, который не был хорошо разработан для концепции функции-члена const.

3 голосов
/ 29 октября 2010

По определению const функция не должна изменять состояние объекта. Но если он вызывает другого неконстантного члена, состояние объекта может измениться, поэтому он запрещен.

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

2 голосов
/ 29 октября 2010

Перегрузка на const:

const int& Second() const
{
    return m_bar;
}

Вы можете добавить этот метод и сохранить исходную неконстантную версию.

1 голос
/ 29 октября 2010

итераторы похожи в этом и делают интересное исследование.

const-итераторы часто являются основой для неконстантных итераторов, и вы часто найдете приведения типа const_cast<>() или C, используемые для отбрасывания const из базового класса с помощью методов доступа в дочернем элементе.

Edit: Комментарий был

У меня есть итератор zip, где константный наследует от неконстантного

Как правило, это неправильная структура наследования (если вы говорите, что я думаю о вас), потому что дети не должны быть менее строгими, чем родители.

скажем, у вас был какой-то алгоритм, принимающий итератор zip, было бы целесообразно передать константный итератор неконстантному?

если у вас есть контейнер const, вы можете запросить его только у const итератора, но тогда const итератор получен из итератора, так что вы просто используете функции родительского элемента, чтобы иметь неконстантный доступ.

Вот краткий план предполагаемого наследования по традиционной модели stl

class ConstIterator: 
    public std::_Bidit< myType, int, const myType *, const mType & >
{
  reference operator*() const { return m_p; }
}

class Iterator : public ConstIterator 
{
  typedef ConstIterator _Mybase;
  // overide the types provided by ConstIterator
  typedef myType * pointer;
  typedef myType & reference;

  reference operator*() const
  { 
    return ((reference)**(_Mybase *)this);
  }
}

typedef std::reverse_iterator<ConstIterator> ConstReverseIterator;
typedef std::reverse_iterator<Iterator> ReverseIterator;
0 голосов
/ 27 декабря 2012

Я обнаружил, что пытаюсь вызвать неконстантную функцию-член, которая была унаследована, но фактически была константой из-за API, который я использовал.Наконец, я остановился на другом решении: заново согласовать API, чтобы унаследованная мной функция была правильной.

Не всегда возможно договориться об изменениях функций других, но это возможно, когда это возможно.чище и приятнее, чем необходимость использовать const_cast, и это приносит пользу и другим пользователям.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...