Модераторы: Daevaorn

Поиск:

Ответ в темуСоздание новой темы Создание опроса
> включение вложенных определений посредством includ 
V
    Опции темы
J0ker
Дата 6.5.2009, 22:00 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Опытный
**


Профиль
Группа: Участник
Сообщений: 986
Регистрация: 17.9.2008

Репутация: 4
Всего: 14



возник такой вопрос
допустим имеется определение класса в который вложены определения других классов
естественно все это трудно читаемо
кошерно-ли вынести оперделения вложенных классов в отдельные файлы, а затем эти файлы вставить посредством #include?
пример:

a.def
Код

class A
{
};


b.def
Код

class B
{
};


c.h
Код

class C
{
private:
    #include "a.def"
public:
    #include "b.def"
};




--------------------
user posted image
PM MAIL   Вверх
Lazin
Дата 6.5.2009, 22:31 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Эксперт
****


Профиль
Группа: Завсегдатай
Сообщений: 3820
Регистрация: 11.12.2006
Где: paranoid oil empi re

Репутация: 41
Всего: 154



а что мешает сделать так:

файл detail/C.h
Код

namespace detail
{
  class A {...};
  class B {...};
}


файл С.h
Код


#include <detail/C.h>

class C
{
public:
typedef detail::A A;
typedef detail::B B;
};

PM MAIL Skype GTalk   Вверх
J0ker
Дата 6.5.2009, 22:49 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Опытный
**


Профиль
Группа: Участник
Сообщений: 986
Регистрация: 17.9.2008

Репутация: 4
Всего: 14



Lazin, хорошее решение, однако не всегда применимое:
Код

class B
{
    class A
    {
        B *b;
        void foo()
        {
            b->i;
        }
    };
private:
    int i;
};


...хотя можно и зафрендить...
но думаю найдутся и другие недостатки

Это сообщение отредактировал(а) J0ker - 6.5.2009, 22:52


--------------------
user posted image
PM MAIL   Вверх
azesmcar
Дата 6.5.2009, 23:11 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


uploading...
****


Профиль
Группа: Участник Клуба
Сообщений: 6291
Регистрация: 12.11.2004
Где: Армения

Репутация: 81
Всего: 211



Код

//header_a_h

class A
{
private:
    class B;
};


Код

//header_b_h

#include "a.h"

class A::B
{
};

Так не пойдет?

Добавлено через 6 минут и 16 секунд
J0ker

Насчет варианта с индклудами - это на мой взгляд не кашерно, ибо обявление класса дублируется и несмотря на то что он обявлен в private секции методом инклуда, его обявлении прекрасно будет фигурировать в глобальном пространстве имен нарушая всю вашу инкапсуляцию smile 
PM   Вверх
mes
Дата 6.5.2009, 23:39 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


любитель
****


Профиль
Группа: Участник Клуба
Сообщений: 7954
Регистрация: 14.1.2006

Репутация: 144
Всего: 250



Цитата(J0ker @  6.5.2009,  21:00 Найти цитируемый пост)
кошерно-ли вынести оперделения вложенных классов в отдельные файлы, а затем эти файлы вставить посредством #include?

думаю не стоит так делать.

мне кажетеся Вам подойдет такой вариант : 

Код

// c.h
class C
{
  class A;
  class B;
//...
private:
   A  * p_a;
   B  * p_b;
};


Код

// c_a.h
#include "c.h"
class C::A
{
};


Код

// c_b.h
#include "c.h"
class C::B
{
};


Код

// c.cpp
#include "c.h"
#include "c_a.h"
#include "c_b.h"

C::C() { p_a = new A(); p_b=new B(); }


Оп...оказывается я опоздал с предложением ;)



Это сообщение отредактировал(а) mes - 7.5.2009, 00:00


--------------------
PM MAIL WWW   Вверх
J0ker
Дата 7.5.2009, 01:23 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Опытный
**


Профиль
Группа: Участник
Сообщений: 986
Регистрация: 17.9.2008

Репутация: 4
Всего: 14



Цитата(azesmcar @  6.5.2009,  23:11 Найти цитируемый пост)
Так не пойдет?

Цитата(mes @  6.5.2009,  23:39 Найти цитируемый пост)
мне кажетеся Вам подойдет такой вариант :

да, похоже это то, что нужно
было-бы еще интересно узнать мнение UnrealMan'а - эквивалентно ли это семантически прямому включению

Цитата(azesmcar @  6.5.2009,  23:11 Найти цитируемый пост)
Насчет варианта с индклудами - это на мой взгляд не кашерно, ибо обявление класса дублируется 

это каким таким образом?

Цитата(azesmcar @  6.5.2009,  23:11 Найти цитируемый пост)
и несмотря на то что он обявлен в private секции методом инклуда, его обявлении прекрасно будет фигурировать в глобальном пространстве имен нарушая всю вашу инкапсуляцию 

каким образом оно попадет в глобальное пространство?


--------------------
user posted image
PM MAIL   Вверх
mes
Дата 7.5.2009, 01:40 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


любитель
****


Профиль
Группа: Участник Клуба
Сообщений: 7954
Регистрация: 14.1.2006

Репутация: 144
Всего: 250



Цитата(J0ker @  7.5.2009,  00:23 Найти цитируемый пост)
эквивалентно ли это семантически прямому включению

В данном вопросе Вы подразумеваете, будут ли на классы описанные вышеупомянутым способом, распространяться те же правила, как если бы он был описан внутри класса-хозяина ?

если да, то 
Цитата

  9.7  Nested class declarations                            [class.nest]

1 A class can be defined within another class.  A class  defined  within
  another is called a nested class.  The name of a nested class is local
  to its enclosing class.  The nested class  is  in  the  scope  of  its
  enclosing  class.   Except by using explicit pointers, references, and
  object names, declarations in a nested class can use only type  names,
  static members, and enumerators from the enclosing class.  [Example:
          int x;
          int y;

          class enclose {
          public:
              int x;
              static int s;
              class inner {
                  void f(int i)
                  {
                      int a = sizeof(x); // error: refers to enclose::x
                      x = i;   // error: assign to enclose::x
                      s = i;   // ok: assign to enclose::s
                      ::x = i; // ok: assign to global x
                      y = i;       // ok: assign to global y
                  }
                  void g(enclose* p, int i)
                  {
                      p->x = i;   // ok: assign to enclose::x
                  }
              };
          };

          inner* p = 0;   // error `inner' not in scope
   --end example]

2 Member  functions  and  static  data  members of a nested class can be
  defined in a namespace scope enclosing the definition of their  class.
  [Example:

          class enclose {
          public:
              class inner {
                  static int x;
                  void f(int i);
              };
          };
          int enclose::inner::x = 1;

          void enclose::inner::f(int i) { /* ... */ }
   --end example]

3 If  class  X  is defined in a namespace scope, a nested class Y may be
  declared in class X and later defined in the definition of class X  or
  be  later  defined  in  a  namespace scope enclosing the definition of
  class X.  [Example:
          class E {
              class I1;      // forward declaration of nested class
              class I2;
              class I1 {};  // definition of nested class
          };
          class E::I2 {};   // definition of nested class
   --end example]

4 Like a member function, a  friend  function  (_class.friend_)  defined
  within  a nested class is in the lexical scope of that class; it obeys
  the same rules for name binding as a static member  function  of  that
  class  (_class.static_) and has no special access rights to members of
  an enclosing class.


 smile 

Это сообщение отредактировал(а) mes - 7.5.2009, 01:45


--------------------
PM MAIL WWW   Вверх
J0ker
Дата 7.5.2009, 06:27 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Опытный
**


Профиль
Группа: Участник
Сообщений: 986
Регистрация: 17.9.2008

Репутация: 4
Всего: 14



mes, спасибо было лень самому копать  smile 

Это сообщение отредактировал(а) J0ker - 7.5.2009, 08:51


--------------------
user posted image
PM MAIL   Вверх
azesmcar
Дата 7.5.2009, 07:04 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


uploading...
****


Профиль
Группа: Участник Клуба
Сообщений: 6291
Регистрация: 12.11.2004
Где: Армения

Репутация: 81
Всего: 211



Цитата(J0ker @  7.5.2009,  01:23 Найти цитируемый пост)
каким образом оно попадет в глобальное пространство? 

методом прямого инклуда файла a.def smile
не знаю можно ли это считать нарушением инкапсуляции, на самом деле если человеку не терпится навредить себе, он это сделает..ведь
Код

#define private public

еще не отменяли smile 
но в любом случае, вышеупомянутый вариант - лучше
PM   Вверх
J0ker
Дата 7.5.2009, 08:51 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Опытный
**


Профиль
Группа: Участник
Сообщений: 986
Регистрация: 17.9.2008

Репутация: 4
Всего: 14



Цитата(azesmcar @  7.5.2009,  07:04 Найти цитируемый пост)
методом прямого инклуда файла a.def

инклюд просто включает текст из одного файла в другой
если я делаю инклюд в скопе класса, то все, что в инклюде написано попадает в скоп класса и никаким боком наружу
впрочем вопрос решен уже


--------------------
user posted image
PM MAIL   Вверх
azesmcar
Дата 7.5.2009, 09:00 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


uploading...
****


Профиль
Группа: Участник Клуба
Сообщений: 6291
Регистрация: 12.11.2004
Где: Армения

Репутация: 81
Всего: 211



Цитата

инклюд просто включает текст из одного файла в другой
если я делаю инклюд в скопе класса, то все, что в инклюде написано попадает в скоп класса и никаким боком наружу
впрочем вопрос решен уже 

А я что-то другое сказал?
Код

class A
{
private:
   #include "b.def"
}

теперь если я - пользователь класса сделаю у себя в начале файла
#include "b.def"
класс В попадет в мое глобальное пространство имен, и он не будет защищен секцией private. Я об этом.
т.е. мы даем пользователю возможность включить этот файл у себя. Ничего особо страшного, но лучше этого не позволять.

Это сообщение отредактировал(а) azesmcar - 7.5.2009, 09:02
PM   Вверх
mes
Дата 7.5.2009, 09:05 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


любитель
****


Профиль
Группа: Участник Клуба
Сообщений: 7954
Регистрация: 14.1.2006

Репутация: 144
Всего: 250



Цитата(azesmcar @  7.5.2009,  08:00 Найти цитируемый пост)
теперь если я - пользователь класса сделаю у себя в начале файла
#include "b.def"
класс В попадет в мое глобальное пространство имен, и он не будет защищен секцией private. Я об этом.


а кто разрешает пользователю инклудить "не инклудные" файлы ?! 
J0ker же специально обозвал его *.def  smile 
В таком случае однозначно ответственность на юзере. 
Также как если вдруг ему захочется заинклудить *cpp файл (хотя бывают случаи и с таким применением smile )



--------------------
PM MAIL WWW   Вверх
azesmcar
Дата 7.5.2009, 09:10 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


uploading...
****


Профиль
Группа: Участник Клуба
Сообщений: 6291
Регистрация: 12.11.2004
Где: Армения

Репутация: 81
Всего: 211



Цитата

Также как если вдруг ему захочется заинклудить *cpp файл (хотя бывают случаи и с таким применением smile )

ну, с большей долей вероятности при включении *cpp файла он получит ошибку времени линковки.
Цитата

а кто разрешает пользователю инклудить "не инклудные" файлы ?! 
J0ker же специально обозвал его *.def  smile 
В таком случае однозначно ответственность на юзере. 

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

PM   Вверх
mes
Дата 7.5.2009, 09:33 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


любитель
****


Профиль
Группа: Участник Клуба
Сообщений: 7954
Регистрация: 14.1.2006

Репутация: 144
Всего: 250



Цитата(azesmcar @  7.5.2009,  08:10 Найти цитируемый пост)
я только говорю что - зачем давать пользователю лишний шанс нарушить инкапсуляцию, если есть другие методы.

от не сознательных действий юзера можно было бы, например, поставить защиту :
Код

class C
#define  MY_KEY_FOR_INCLUDE_B_DEF_H_
#include "b.def"
#undef  MY_KEY_FOR_INCLUDE_B_DEF_H_

//b.def
#ifdef MY_KEY_FOR_INCLUDE_B_DEF_H_
..
#endif 

но, имхо, дело не в пользователe, а в самой постановке кода. Если есть более чистый вариант, зачем прибегать к трюкам ?! 

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


Цитата(azesmcar @  7.5.2009,  08:10 Найти цитируемый пост)
ну, с большей долей вероятности при включении *.cpp файла он получит ошибку времени линковки.

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


Это сообщение отредактировал(а) mes - 7.5.2009, 09:40


--------------------
PM MAIL WWW   Вверх
azesmcar
Дата 7.5.2009, 09:55 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


uploading...
****


Профиль
Группа: Участник Клуба
Сообщений: 6291
Регистрация: 12.11.2004
Где: Армения

Репутация: 81
Всего: 211



Цитата(mes @  7.5.2009,  09:33 Найти цитируемый пост)
но, имхо, дело не в пользователe, а в самой постановке кода. Если есть более чистый вариант, зачем прибегать к трюкам ?! 

ну я и говорю
Цитата(azesmcar @  7.5.2009,  09:10 Найти цитируемый пост)
если есть другие методы.


Цитата(mes @  7.5.2009,  09:33 Найти цитируемый пост)

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

это те cpp шники которые специально для этого разработаны, я говорил не о них а об обычных.

PM   Вверх
mes
Дата 7.5.2009, 10:03 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


любитель
****


Профиль
Группа: Участник Клуба
Сообщений: 7954
Регистрация: 14.1.2006

Репутация: 144
Всего: 250



Цитата(azesmcar @  7.5.2009,  08:55 Найти цитируемый пост)
это те cpp шники которые специально для этого разработаны, я говорил не о них а об обычных.

ну так а b.def разве не специально разработан ?!  smile   smile 


Цитата(azesmcar @  7.5.2009,  08:55 Найти цитируемый пост)
ну я и говорю

я лишь пытался уточнить, потому как чуствовалась двойная трактовка, но в принципе, да, речь об одном и том же  smile 


--------------------
PM MAIL WWW   Вверх
azesmcar
Дата 7.5.2009, 10:06 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


uploading...
****


Профиль
Группа: Участник Клуба
Сообщений: 6291
Регистрация: 12.11.2004
Где: Армения

Репутация: 81
Всего: 211



Цитата

ну так а b.def разве не специально разработан ?! 

специально, только вот если включить те файлы шаблонных функций - то ничего не нарушится, они специально предназначены для включения в глобальное пространство имен, а наш b.def предназначен для включения в приватную секцию (хотя никто не зарпещает включить его глобально).  smile 
В принципе это параноя если смотреть с практической точки зрения smile
Но если взглянуть с теоретической точки зрения, то есть более рациональный аналог. Только и всего smile
PM   Вверх
J0ker
Дата 7.5.2009, 16:33 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Опытный
**


Профиль
Группа: Участник
Сообщений: 986
Регистрация: 17.9.2008

Репутация: 4
Всего: 14



Цитата(azesmcar @  7.5.2009,  10:06 Найти цитируемый пост)
специально, только вот если включить те файлы шаблонных функций - то ничего не нарушится, они специально предназначены для включения в глобальное пространство имен, а наш b.def предназначен для включения в приватную секцию (хотя никто не зарпещает включить его глобально).

boost/mem_fn.hpp
Код

......
namespace _mfi // mem_fun_impl
{

template<class V> struct mf
{

#define BOOST_MEM_FN_RETURN return

#define BOOST_MEM_FN_NAME(X) inner_##X
#define BOOST_MEM_FN_CC

#include <boost/bind/mem_fn_template.hpp>

#undef BOOST_MEM_FN_CC
#undef BOOST_MEM_FN_NAME
.........

boost/bind/mem_fn_template.hpp
Код

//
//  bind/mem_fn_template.hpp
//
//  Do not include this header directly
//
....



--------------------
user posted image
PM MAIL   Вверх
azesmcar
Дата 7.5.2009, 16:35 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


uploading...
****


Профиль
Группа: Участник Клуба
Сообщений: 6291
Регистрация: 12.11.2004
Где: Армения

Репутация: 81
Всего: 211



J0ker smile 
mes сказал немного выше что так поступают в стандартных библиотеках..но только когда другого выхода нет.

PM   Вверх
J0ker
Дата 7.5.2009, 17:04 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Опытный
**


Профиль
Группа: Участник
Сообщений: 986
Регистрация: 17.9.2008

Репутация: 4
Всего: 14



Цитата(azesmcar @  7.5.2009,  16:35 Найти цитируемый пост)
J0ker  
mes сказал немного выше что так поступают в стандартных библиотеках..но только когда другого выхода нет.


Цитата(azesmcar @  7.5.2009,  10:06 Найти цитируемый пост)
 а наш b.def предназначен для включения в приватную секцию (хотя никто не зарпещает включить его глобально).  

а наш boost/bind/mem_fn_template.hpp предназначен для включения в публичную секцию (хотя никто не зарпещает включить его глобально)


Это сообщение отредактировал(а) J0ker - 7.5.2009, 17:05


--------------------
user posted image
PM MAIL   Вверх
azesmcar
Дата 7.5.2009, 17:13 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


uploading...
****


Профиль
Группа: Участник Клуба
Сообщений: 6291
Регистрация: 12.11.2004
Где: Армения

Репутация: 81
Всего: 211



Цитата(J0ker @  7.5.2009,  17:04 Найти цитируемый пост)
а наш boost/bind/mem_fn_template.hpp предназначен для включения в публичную секцию (хотя никто не зарпещает включить его глобально)

Видимо у них были на то причины. Я все равно считаю это последним решением к которому можно прибегнуть. Я не изучал глубоко этот файл и не знаю причин которые могли побудить авторов написать этот код, и не могу сказать что у них был другой выбор.
PM   Вверх
Страницы: (2) [Все] 1 2 
Ответ в темуСоздание новой темы Создание опроса
Правила форума "С++:Общие вопросы"
Earnest Daevaorn

Добро пожаловать!

  • Черновик стандарта C++ (за октябрь 2005) можно скачать с этого сайта. Прямая ссылка на файл черновика(4.4мб).
  • Черновик стандарта C (за сентябрь 2005) можно скачать с этого сайта. Прямая ссылка на файл черновика (3.4мб).
  • Прежде чем задать вопрос, прочтите это и/или это!
  • Здесь хранится весь мировой запас ссылок на документы, связанные с C++ :)
  • Не брезгуйте пользоваться тегами [code=cpp][/code].
  • Пожалуйста, не просите написать за вас программы в этом разделе - для этого существует "Центр Помощи".
  • C++ FAQ

Если Вам понравилась атмосфера форума, заходите к нам чаще! С уважением, Earnest Daevaorn

 
0 Пользователей читают эту тему (0 Гостей и 0 Скрытых Пользователей)
0 Пользователей:
« Предыдущая тема | C/C++: Общие вопросы | Следующая тема »


 




[ Время генерации скрипта: 0.0892 ]   [ Использовано запросов: 22 ]   [ GZIP включён ]


Реклама на сайте     Информационное спонсорство

 
По вопросам размещения рекламы пишите на vladimir(sobaka)vingrad.ru
Отказ от ответственности     Powered by Invision Power Board(R) 1.3 © 2003  IPS, Inc.