DEEP_CONST
От: _Winnie Россия C++.freerun
Дата: 10.01.06 12:53
Оценка: -1
Здравствуйте, eao197, Вы писали:

>И еще, где можно прочитать про гламурность, очарование и шарм в программах?

Ну...
Смотри, что я придумал:

const означает, что мы не можем менять ноду.
DEEP_CONST означает ноду и всех её потомков.

#ifdef NDEBUG
#define DEEP_CONST const
#else
#define DEEP_CONST const volatile
#define DEEP_CONST_DEFINED
#endif

struct TreeNode
{
private:
    TreeNode *right, *left;
    int value;

public:
    int get_val() DEEP_CONST { return value; }

    void set_value(int i) { value = i; }


    TreeNode *get_right() const { return right; };
    TreeNode *get_left() const { return left; };

#if defined(DEEP_CONST_DEFINED) 
    TreeNode DEEP_CONST *get_right() DEEP_CONST { return right; };
    TreeNode DEEP_CONST *get_left() DEEP_CONST { return left; };
#endif
};


void f(TreeNode DEEP_CONST *t)
{
    t->get_right()->set_value(10); //ошибка
    t->get_right()->get_val(); //ok
}

void g(TreeNode const *t)
{
    t->get_right()->set_value(10); //ok
}

int main()
{
}


Может, у тебя есть ещё какие-то идеи?

10.01.06 22:21: Ветка выделена из темы DEEP_CONST
Автор: _Winnie
Дата: 09.01.06
— Кодт
10.01.06 22:22: Перенесено модератором из 'Мусор' — Кодт
Правильно работающая программа — просто частный случай Undefined Behavior
Re[4]: DEEP_CONST
От: eao197 Беларусь http://eao197.blogspot.com
Дата: 10.01.06 13:12
Оценка:
Здравствуйте, _Winnie, Вы писали:

_W>const означает, что мы не можем менять ноду.

_W>DEEP_CONST означает ноду и всех её потомков.

_W>
...
_W>struct TreeNode
_W>{
...
_W>    TreeNode *get_right() const { return right; };
_W>    TreeNode *get_left() const { return left; };
...
_W>};
...
_W>


_W>Может, у тебя есть ещё какие-то идеи?


Да, есть. Если метод get_right() является const, то и возвращать он должен const TreeNode *. А если мне нужен дочерний узел для изменения, но при этом я владею только константным указателем на родителя (уже странно, не находишь?), то не лучше ли сделать отдельные методы: get_writeable_right() и get_writeable_left()?


SObjectizer: <микро>Агентно-ориентированное программирование на C++.
Re[5]: DEEP_CONST
От: _banned_dobrokot livejournal.com/users/banned_dobrokot/
Дата: 11.01.06 08:20
Оценка:
Здравствуйте, eao197, Вы писали:

E>Здравствуйте, _Winnie, Вы писали:


_W>>const означает, что мы не можем менять ноду.

_W>>DEEP_CONST означает ноду и всех её потомков.


E>Да, есть. Если метод get_right() является const, то и возвращать он должен const TreeNode *.


Обрати внимание, класс называется Tree
Node
а не Tree.
а константность ноды не должна обозначать константность всего дерева.
Если бы класс назывался Tree, тогда бы да, get_right дожен сохранять константность подобъектов. Но поскольку это Node, а не Tree, то что справа и слева — не подобъекты.

> А если мне нужен дочерний узел для изменения, но при этом я владею только константным указателем на родителя (уже странно, не находишь?), то не >лучше ли сделать отдельные методы: get_writeable_right() и get_writeable_left()?


Ну и про модификатор const тоже можно сказать, что он не нужен, и что "просто не вызывайте функцию set_value" как и "не вызывайте *writable функции"
Достоинство квалификаторов — что компилятор проверит их сквозь десяток вызовов функций, во всей программе, даже в самом запутанном индусском коде-лапше.
Re[5]: DEEP_CONST
От: _banned_dobrokot livejournal.com/users/banned_dobrokot/
Дата: 11.01.06 08:23
Оценка:
Здравствуйте, eao197, Вы писали:

Ща более интересный примерчик наклепаю...
Re[6]: DEEP_CONST
От: eao197 Беларусь http://eao197.blogspot.com
Дата: 11.01.06 08:49
Оценка:
Здравствуйте, _banned_dobrokot, Вы писали:

>> А если мне нужен дочерний узел для изменения, но при этом я владею только константным указателем на родителя (уже странно, не находишь?), то не >лучше ли сделать отдельные методы: get_writeable_right() и get_writeable_left()?


__>Ну и про модификатор const тоже можно сказать, что он не нужен, и что "просто не вызывайте функцию set_value" как и "не вызывайте *writable функции"

__>Достоинство квалификаторов — что компилятор проверит их сквозь десяток вызовов функций, во всей программе, даже в самом запутанном индусском коде-лапше.

Не понимаю, к чему ты это сказал. Если следовать моему предложению, то нет соглащений на уровне "просто не вызывайте вот это вот". Если есть const TreeNode и вызывается get_right, то получаем опять const TreeNode. Компилятор проверяет все квалификаторы, везде.

Но я бы, если бы мне пришлось делать какие-то подобные выкрутасы с деревьями, пошел бы еще дальше. Куда-то вот в эту степь:
class Writeable_Child_Accessor
  {
  public :
    TreeNode * get_right() const;
    TreeNode * get_left() const;
  ... /* Детали реализации */ ...
  };
class Nonwriteable_Child_Accessor
  {
  public :
    const TreeNode * get_right() const;
    const TreeNode * get_left() const;
  ... /* Детали реализации */ ...
  };

void f( Nonwriteable_Child_Accessor & node )
  {
    node.get_right()->set_value( 10 ); // БУМС! Получаем ошибку!
  }

void g( Writeable_Child_Accessor & node )
  {
    node.get_right()->set_value( 10 ); // Все нормально.
  }


Вот, в первом приближении, что-нибудь такое. Или дальше подумать, чтобы сам TreeNode реализовывал несколько интерфейсов (с тем, чтобы имея Nonwritable_Child_Accessor нельзя было через get_right()/get_left() получить Writeable_Child_Accessor для их дочерних узлов).


SObjectizer: <микро>Агентно-ориентированное программирование на C++.
 
Подождите ...
Wait...
Пока на собственное сообщение не было ответов, его можно удалить.