реклама на сайте
подробности

 
 
> Доступ к методам (функциям) класса., Выбор оптимального способа
Stas633
сообщение Oct 13 2008, 21:44
Сообщение #1


Частый гость
**

Группа: Свой
Сообщений: 105
Регистрация: 6-01-06
Пользователь №: 12 901



Допустим:
- имеются два класса TOne и TTwo;
- в TOne определена ф-ция FuncOne();
- классы определены в разных единицах компиляции (файлах);
- созданы объекты (глобальные) этих классов (mOne и mTwo) в третьем файле - "main.cpp".
Вопрос:
Как из класса TTwo получить доступ (использовать) функцию FuncOne() класса TOne?

1. наследовать TOne в TTwo
2. перед описанием класса TTwo объявить объект классаа TOne: extern TOne mOne.
3. ...?
...
А если таких "вложений" больше? (Т.е. функции TTwo, использующие TOne, необходимы в TThree)

Что лучше? Как правильнее? Есть ли разница в испозовании стека?

Прим. Например: TOne - класс описывающий работу с индикатором (LCD), а TTwo - класс формирования данных для вывода на индикатор. Рассматривается ситуация одного процесса (не RTOS).

Прим.1 Вопрос задаю здесь, так как обсуждение темы о выделении раздела форума для "чистого" программирования, увы, ни к чему не привело. smile.gif Господа Админы/Модераторы извините, просмотрел..
Go to the top of the page
 
+Quote Post
 
Start new topic
Ответов
vik0
сообщение Oct 15 2008, 09:39
Сообщение #2


Местный
***

Группа: Свой
Сообщений: 381
Регистрация: 27-07-08
Из: теплые края
Пользователь №: 39 233



Вставлю и я свои 5 копеек smile.gif
1. Если у Вас TOne - таки LCD, то можно использовать статические функции. Ведь LCD у вас в системе один, правильно?
Код
class TOne
{
  static int memberVar;
public:
  static void Foo() {}
};
.....
class TTwo
{
public:
  void Bar()
  {
     TOne::Foo();
  }
};

2. Если TOne - не LCD (или у вас в системе их несколько smile.gif ), тогда правильнее передавать указатель на TOne в ф-цию ининциализации
Код
class TOne
{
public:
  void Foo() {}
};
.....
class TTwo
{
  TOne* oneInstance;
public:
  void Init(TOne* one)
  {
    oneInstance = one;
  }

  void Bar()
  {
     oneInstance->Foo();
  }
};
...
TOne mOne;
TTwo mTwo;

int main(int, char**)
{
  mTwo.Init(&mOne);
  mTwo.Bar();
  ....
}


А friend тут не причем. У человека, по-моему, проблемы не с правами доступа к членам класса, а с доступом (работой) к глобальным переменным.
Go to the top of the page
 
+Quote Post
Stas633
сообщение Oct 15 2008, 11:18
Сообщение #3


Частый гость
**

Группа: Свой
Сообщений: 105
Регистрация: 6-01-06
Пользователь №: 12 901



Чтобы не было "гаданий на кофейной гуще" опишу коротко "историю" возникновения вопроса... Хоть с темой это и не связано.
- была рабочая программа на Си. Программа содержала готовые "блоки" для работы с LCD, интерфейсы I2C, SPI, UART, работа с кнопками, энкодером и т.д;
- при "проектировании" нового изделия было принято решение о переходе на С++ (причины принятия решения опускаю);
- мне показалось достаточным "обозвать" (объявить) блоки классами. Для доступности функций интерфейса (LCD и т.д.) и проводилось прямое, читай - бездумное, наследование.
- пока объема озу (стека) хватало для размещения всех копий базовых классов все было "спокойно"... А как только порог был превышен, так сразу и появился, вопрос, вынесенный в топик. Поэтому подтекст вопроса примерно такой: "Как можно обратиться к функции, объявленной в другом классе (члену другото класса - так правильнее smile.gif ), без "потери" памяти на это обращение". Но в таком виде писать вопрос в TOP стыдно .. (видимо напрасно стыжусь - учиться никогда не поздно).

И friend и static весьма "полезны": friend позволяет получить доступ без создания копий (т.е. буквально то, что я хотел), а обявление элемента с квалификатором static гарантирует, что будет создана только одна копия этого элемента. (Пишу очевидные вещи для таких как я начинающих С++).

Еще раз спасибо.

"...Чем лучше программист знает С, тем труднее будет для него при программировании на С++ отойти от
стиля программирования на С...." (с) Бьерн Страуструп.

....
А чем наследование лучше/хуже доступа через friend? (для рассматриваемого случая)
Go to the top of the page
 
+Quote Post
bookevg
сообщение Nov 6 2008, 12:45
Сообщение #4


Местный
***

Группа: Свой
Сообщений: 320
Регистрация: 13-09-06
Пользователь №: 20 348



Цитата(Stas633 @ Oct 15 2008, 14:18) *
Чтобы не было "гаданий на кофейной гуще" опишу коротко "историю" возникновения вопроса... Хоть с темой это и не связано.
- была рабочая программа на Си. Программа содержала готовые "блоки" для работы с LCD, интерфейсы I2C, SPI, UART, работа с кнопками, энкодером и т.д;
...
И friend и static весьма "полезны": friend позволяет получить доступ без создания копий (т.е. буквально то, что я хотел), а обявление элемента с квалификатором static гарантирует, что будет создана только одна копия этого элемента. (Пишу очевидные вещи для таких как я начинающих С++).


В таких случаях как приведен выше использую класс со всеми методами объявленными как static (в C# почти что все библиотечные функции статические методы класса). С friend-м надо лучше концепцию продумать.


Цитата(Stas633 @ Oct 15 2008, 14:18) *
....
А чем наследование лучше/хуже доступа через friend? (для рассматриваемого случая)

Наследование хорошо использовать но, надо заметить, что возможно два основных случая:
-замещение;
-виртуальность.
Использование виртуальности ведет к повышенному расходу памяти (создание v-таблицы) и снижение производительности
Go to the top of the page
 
+Quote Post
Stas633
сообщение Nov 7 2008, 07:25
Сообщение #5


Частый гость
**

Группа: Свой
Сообщений: 105
Регистрация: 6-01-06
Пользователь №: 12 901



Цитата(bookevg @ Nov 6 2008, 15:45) *
...

Спасибо. Согласен... Наследование для решения вопроса доступа - это, как минимум, не экономно.
...
Если говорить по теме, то вопрос доступа решил так, как рекомендовал dxp.
А именно:
- каждый объект "размещен" в своей "единице компиляции" (ЕдКомп) /связка файлов, например, One.h и One.cpp/ (так делал и раньше);
- член класса /TOne mTOne;/ объявляется теперь в TOne.cpp, а не в main.cpp как раньше;
- а для возможности использования функций (свойств) TOne, там где нужно, mTOne объявляется с квалификатором extern.

... файл One.h
Код
...
class TOne
{
...
public:
void FuncOne(void);
...
}

... файл One.cpp
Код
...
TOne mTOne;
....
void FuncOne(void)
{
}

... файл Two.h
Код
...
class TTwo
{
...
public:
void FuncTwo(void);
...
}

... файл Two.cpp
Код
....
#include "One.h"

TTwo mTTwo;
extern TOne mTOne;
....
void FuncTwo(void)
{
...
mTOne.FuncOne();
...
}

На мой взгляд, наиболее простой и понятный способ.

А если говорить не совсем по теме, то главная проблема ("разруха" в первоисточнике) "...в головах, а не в клозетах..." (с) Нельзя заниматься ООП оперируя процедурами. Как только приходишь к пониманию "объекта", так все очень упрощается. И "создание" (представление) модели программы, и понимание взаимоотношений между разными частями этой программы. Не буду пересказывать написанное Гради Бучем (и про мыслительный процесс человека в повседневной жизни, и про количество абстракций, с которыми человек способен работать одновременно, и т.д.), но, на мой взгляд, достаточно прочесть главу "1.2. Структура сложных систем" и вопросов о полезности и естественности перехода к ООП не остается. Мир вокруг нас состоит из Объектов, а не из Процедур. И живем мы, используя Объекты и их какие-то свойсва (Процедуры), а не Процедуры каких-то Объектов.
Go to the top of the page
 
+Quote Post
Stas633
сообщение Nov 21 2008, 20:03
Сообщение #6


Частый гость
**

Группа: Свой
Сообщений: 105
Регистрация: 6-01-06
Пользователь №: 12 901



Поиск "оптимального" решения продолжается....
Позволю себе напомнить "проблему"...
Есть некий объект (класс), допустим, модуль отладки (DBGU) через UART. Естественно, объект может (и должен) инициализироваться, принимать и передавать инфу, и др.
Свойства (функции, методы....) этого объекта (класса), ес-но должны быть доступны другим, если не сказать всем остальным, объектам. При этом, все остальные обекты могут находиться в "родительско-наследственных" отношениях. Как получить доступ к функциям DBGU?

То, что использовать наследование DBGU для получения доступа к его свойсвам, не рационально описано выше в теме. Содание класса TDBGU как виртуального гарантирует, что при косвенном ("вложенном") наследовании "верхних" классов не будет создано двух копий TDBGU. А если virtual TDBGU наследуется двумя "отдельными" (разными, самостоятельными...) классами, то для каждого будет создана своя копия TDBGU... Или я не прав? И что вообще означает "производный класс содержит копию базового класса"? Про "создание" копий переменных базового класса при наследовании понятно, а как наследуются функции? Просмотр "откомпилированного" кода и здравый смысл подсказывает, что функции наследуются "беззатратно". Но если это так, то при условии остутсвия переменных в базовом классе его копия ничего не "весит"?

Объявление глобального объекта mDBGU с использованием там "где нужно" конструкции extern ... mDBGU так же не лишено недостатков (как способ). Во-первых, глобальный объект "размещается" в "глобальной" области, при этом размещается "раз и навегда". Ну и, во-вторых, нарушается один из первейших принципов ООП - инкапсуляция. (Второе, конечно, относится скорее к стилю программирования нежели к "ошибкам", но если не выполнять правил, то зачем переходить на CPP?). Кстати, натолкнуло на эту мысль упорное "нежелание" IAR инициализировать глобальные объекты при startup'e.

Далее... friend... ЧтО позволяет "делать" функция или класс , объявленные в другом как friend? Использовать функции (свойства) friend класса? НО! только через инициализированный объект mDBGU! А как быть если этот объект еще не "создан" или не "виден"?.... (И вообще, насколько я понял, конструкция friend "нужна" для доступа к privat переменным friend класса.)

Остается доступ к свойствам (функциям) DBGU через их объявление с квалиф. static. Ранее я писал, что "...static гарантирует, что будет создана только одна копия этого элемента...". Это справедливо, но только для переменных (может я ошибаюсь?). Для функций же это квалификатор "устанавливает" глобальную "видимость" и "доступность" даже до инициализации объекта mDBGU..и только.

Таким образом, объявив ф-цию как в staticах, можно ее "использовать" где угодно, конечно предварительно "показав" ее (класс) через #include. Это очень "смахивает" на Си-подход, но лучшего в голову не приходит... Хотя спинной мозг "подсказывает", что не все так однозначно... smile.gif

Просвятите, плз.
Go to the top of the page
 
+Quote Post
bookevg
сообщение Nov 22 2008, 08:28
Сообщение #7


Местный
***

Группа: Свой
Сообщений: 320
Регистрация: 13-09-06
Пользователь №: 20 348



Цитата(Stas633 @ Nov 21 2008, 23:03) *
Поиск "оптимального" решения продолжается....
Позволю себе напомнить "проблему"...
Есть некий объект (класс), допустим, модуль отладки (DBGU) через UART. Естественно, объект может (и должен) инициализироваться, принимать и передавать инфу, и др.
Свойства (функции, методы....) этого объекта (класса), ес-но должны быть доступны другим, если не сказать всем остальным, объектам. При этом, все остальные обекты могут находиться в "родительско-наследственных" отношениях. Как получить доступ к функциям DBGU?

Я так понимаю различные классы будут обращаться к DBGU - т.о. надо сделать систему доступа к общему ресурсу или создать список заданий для DBGU
Цитата(Stas633 @ Nov 21 2008, 23:03) *
То, что использовать наследование DBGU для получения доступа к его свойсвам, не рационально описано выше в теме. Содание класса TDBGU как виртуального гарантирует, что при косвенном ("вложенном") наследовании "верхних" классов не будет создано двух копий TDBGU. А если virtual TDBGU наследуется двумя "отдельными" (разными, самостоятельными...) классами, то для каждого будет создана своя копия TDBGU... Или я не прав? И что вообще означает "производный класс содержит копию базового класса"? Про "создание" копий переменных базового класса при наследовании понятно, а как наследуются функции? Просмотр "откомпилированного" кода и здравый смысл подсказывает, что функции наследуются "беззатратно". Но если это так, то при условии остутсвия переменных в базовом классе его копия ничего не "весит"?

Мне кажется, что вы неправильно трактуете суть полиморфизма - советую прочитать Дж.Либерти - Освой С++ за 21 день. Попробую автора процитировать:
Можно объвить множество окон разных типов, включая диалоговые, прокручиваемые и поля списков и т.д.), после чего создавать их в программе с помощью единственного виртуального метода draw(). Создав указатель на базовое окно и присваивая этому указателю адреса объектов производных классов, можно обращаться к методу draw() независимо от того, с каким из объектов в данный момент связан указатель. Причем всегда будет вызываться вариант метода, специфичный для класса выбранного объекта.
Цитата(Stas633 @ Nov 21 2008, 23:03) *
Объявление глобального объекта mDBGU с использованием там "где нужно" конструкции extern ... mDBGU так же не лишено недостатков (как способ). Во-первых, глобальный объект "размещается" в "глобальной" области, при этом размещается "раз и навегда".

А как по вашему работают cin и cout - ведь вы ведь нигде от них не наследуетесь, а они отвечают за ввод и вывод информации
Цитата(Stas633 @ Nov 21 2008, 23:03) *
Ну и, во-вторых, нарушается один из первейших принципов ООП - инкапсуляция. (Второе, конечно, относится скорее к стилю программирования нежели к "ошибкам", но если не выполнять правил, то зачем переходить на CPP?).

Ничего не нарушается.
Цитата(Stas633 @ Nov 21 2008, 23:03) *
Кстати, натолкнуло на эту мысль упорное "нежелание" IAR инициализировать глобальные объекты при startup'e.

До входа в main() все глобальные классы проинициализированы, т.е. вызваны все конструкторы.

Цитата(Stas633 @ Nov 21 2008, 23:03) *
Далее... friend... ЧтО позволяет "делать" функция или класс , объявленные в другом как friend? Использовать функции (свойства) friend класса? НО! только через инициализированный объект mDBGU! А как быть если этот объект еще не "создан" или не "виден"?.... (И вообще, насколько я понял, конструкция friend "нужна" для доступа к privat переменным friend класса.)

Вообще никогда friend-ом не пользуюсь
Цитата(Stas633 @ Nov 21 2008, 23:03) *
Остается доступ к свойствам (функциям) DBGU через их объявление с квалиф. static. Ранее я писал, что "...static гарантирует, что будет создана только одна копия этого элемента...". Это справедливо, но только для переменных (может я ошибаюсь?). Для функций же это квалификатор "устанавливает" глобальную "видимость" и "доступность" даже до инициализации объекта mDBGU..и только.
Таким образом, объявив ф-цию как в staticах, можно ее "использовать" где угодно, конечно предварительно "показав" ее (класс) через #include. Это очень "смахивает" на Си-подход, но лучшего в голову не приходит... Хотя спинной мозг "подсказывает", что не все так однозначно... smile.gif

Static переменные и методы нужны для действий, которые оперируют общими ресурсами для всех экземпляров класса.
Также можно создавать только static классы - что я очень часто и использую - на производительность это никак не сказывается, т.к. компилятор все это сводит к С-реализации

Сообщение отредактировал bookevg - Nov 22 2008, 08:35
Go to the top of the page
 
+Quote Post
Stas633
сообщение Nov 22 2008, 10:09
Сообщение #8


Частый гость
**

Группа: Свой
Сообщений: 105
Регистрация: 6-01-06
Пользователь №: 12 901



Цитата(bookevg @ Nov 22 2008, 11:28) *
Я так понимаю различные классы будут обращаться к DBGU - т.о. надо сделать систему доступа к общему ресурсу или создать список заданий для DBGU

Совершенно верно. Только ЧТО делать понятно, а вот что на счет того КАК делать?

Цитата(bookevg @ Nov 22 2008, 11:28) *
Мне кажется, что вы неправильно трактуете суть полиморфизма - советую прочитать Дж.Либерти - Освой С++ за 21 день. Попробую автора процитировать:
Можно объвить множество окон разных типов, включая диалоговые, прокручиваемые и поля списков и т.д.), после чего создавать их в программе с помощью единственного виртуального метода draw(). Создав указатель на базовое окно и присваивая этому указателю адреса объектов производных классов, можно обращаться к методу draw() независимо от того, с каким из объектов в данный момент связан указатель. Причем всегда будет вызываться вариант метода, специфичный для класса выбранного объекта.

Не соглашусь с Вами. В приведенной цитате речь идет о методах, т.е. виртуальных функциях . Которые естественно должны иметь свое "наполнение" в производных классах. Но я рассуждал не о наследовании виртуальных функций и полиформизме, а о наследовании virtual класса класса как virtual. Как я понимаю, виртуальный класс вовсе не "обязан" содержать виртуальные функции. Более того, виртульные функции можно создавать только в абстактнх классах. То есть объектов таких классов создано быть не может. Просто "не получится". Не так ли?

Цитата(bookevg @ Nov 22 2008, 11:28) *
А как по вашему работают cin и cout - ведь вы ведь нигде от них не наследуетесь, а они отвечают за ввод и вывод информации

Извините, не понял к чему это... Я имел ввиду нецелесообразность обявления global объектов, если есть возможность сделать их локальными.

Цитата(bookevg @ Nov 22 2008, 11:28) *
Ничего не нарушается.

Спорно. Если объект объявляется/выносится за пределы своего "ареала обитания", то разве это соответсвует принципу encapsulation? Зачем в список фруктовых деревьев сада вносить функцию измерения размера косточки плода? Ведь к этой функции все равно придется обращаться, как минимум, через Плод. (На точности примера не настаиваю)

Цитата(bookevg @ Nov 22 2008, 11:28) *
До входа в main() все глобальные классы проинициализированы, т.е. вызваны все конструкторы.

Так должно быть, но не всегда так есть. "Встроенный" Cstartup.s79 для IARARM НЕ СОДЕРЖИТ вызовов конструкторов до входа в main(). На форуме упомянуты способы введения такой инициализации (в частности, Сергеем Борщем).

Цитата(bookevg @ Nov 22 2008, 11:28) *
Вообще никогда friend-ом не пользуюсь

А почему?

Цитата(bookevg @ Nov 22 2008, 11:28) *
Static переменные и методы нужны для действий, которые оперируют общими ресурсами для всех экземпляров класса.

Т.е. данными?

Цитата(bookevg @ Nov 22 2008, 11:28) *
Также можно создавать только static классы - что я очень часто и использую - на производительность это никак не сказывается, т.к. компилятор все это сводит к С-реализации

Другими словами, если не смог (к Вам никакого отношения не имеет!) написать на С++ используй static и пиши как на С... 05.gif
...
И все-таки, если класс не содержит ресурсов (переменных, данных), то будет ли формироваться избыточный код при его "многократном" наследовании?
Go to the top of the page
 
+Quote Post
bookevg
сообщение Nov 24 2008, 13:51
Сообщение #9


Местный
***

Группа: Свой
Сообщений: 320
Регистрация: 13-09-06
Пользователь №: 20 348



Цитата(Stas633 @ Nov 22 2008, 13:09) *
Совершенно верно. Только ЧТО делать понятно, а вот что на счет того КАК делать?
Не соглашусь с Вами. В приведенной цитате речь идет о методах, т.е. виртуальных функциях . Которые естественно должны иметь свое "наполнение" в производных классах. Но я рассуждал не о наследовании виртуальных функций и полиформизме, а о наследовании virtual класса класса как virtual.

Зачем нужно, чтобы весь класс был виртуальным - надо только, чтобы методы были и этого достаточно
Цитата(Stas633 @ Nov 22 2008, 13:09) *
Как я понимаю, виртуальный класс вовсе не "обязан" содержать виртуальные функции.

А зачем тогда он нужен - виртуальность нужна как раз только для методов
Цитата(Stas633 @ Nov 22 2008, 13:09) *
Более того, виртульные функции можно создавать только в абстактнх классах. То есть объектов таких классов создано быть не может. Просто "не получится". Не так ли?

Еще как можно использовать - т.е. объявил класс СTimers1 как обычно, создал вирт.метод СTimers1::Update, затем породил класс СTimers2 от СTimers1 и переписал СTimers1::Update и создал два экземляра СTimers1 Timers1; и СTimers2 Timers2 и работаешь с ними.
Цитата(Stas633 @ Nov 22 2008, 13:09) *
Извините, не понял к чему это... Я имел ввиду нецелесообразность обявления global объектов, если есть возможность сделать их локальными.

Я как понял вашу задачу: вы хотите, чтобы другие объекты через экземпляр класса DBGU общались с внешним миром - но ведь на PC-машинах все наши объекты общаются с внешним миром или через cin/cout или GUI
Цитата(Stas633 @ Nov 22 2008, 13:09) *
Спорно. Если объект объявляется/выносится за пределы своего "ареала обитания", то разве это соответсвует принципу encapsulation? Зачем в список фруктовых деревьев сада вносить функцию измерения размера косточки плода? Ведь к этой функции все равно придется обращаться, как минимум, через Плод. (На точности примера не настаиваю)

А зачем почти что всем животным воздух?
Цитата(Stas633 @ Nov 22 2008, 13:09) *
Так должно быть, но не всегда так есть. "Встроенный" Cstartup.s79 для IARARM НЕ СОДЕРЖИТ вызовов конструкторов до входа в main(). На форуме упомянуты способы введения такой инициализации (в частности, Сергеем Борщем).

Незамечал, я обычно всегда делаю свой Cstartup.s79, так что мог и ошибиться, но вроде еще с AVR глобаль.объекты инициализировал компилятор - даже пришлось убрать инициализацию из конструкторов, чтоб все происходило по порядку определяемому мною
Цитата(Stas633 @ Nov 22 2008, 13:09) *
А почему?

Пока нужды не возникало использование friend, если и порывался. то находил другие пути выхода из ситуации, да и не все embedded компиляторы поддерживали это лет 4-6 назад.
Цитата(Stas633 @ Nov 22 2008, 13:09) *
Т.е. данными?

Необязательно, м.б. и общие действия, но в принципе все равно все сводится к данным
Цитата(Stas633 @ Nov 22 2008, 13:09) *
Другими словами, если не смог (к Вам никакого отношения не имеет!) написать на С++ используй static и пиши как на С... 05.gif

Все проекты разрабатываются в Microsoft Visual Studio - при оформлении классом одновременно улучшается читабельность кода
Цитата(Stas633 @ Nov 22 2008, 13:09) *
...
И все-таки, если класс не содержит ресурсов (переменных, данных), то будет ли формироваться избыточный код при его "многократном" наследовании?

Зависит от умности компилятора и линкера.
Go to the top of the page
 
+Quote Post

Сообщений в этой теме
- Stas633   Доступ к методам (функциям) класса.   Oct 13 2008, 21:44
- - igorenja   Цитата(Stas633 @ Oct 14 2008, 03:44) Я ...   Oct 14 2008, 05:19
- - dxp   Цитата(Stas633 @ Oct 14 2008, 04:44) Что ...   Oct 14 2008, 08:12
|- - Stas633   Ув. dxp, спасибо за Ваши советы/рекомендации (в др...   Oct 14 2008, 20:58
|- - dxp   Цитата(Stas633 @ Oct 15 2008, 03:58) Что ...   Oct 15 2008, 04:32
|- - Stas633   Цитата(dxp @ Oct 15 2008, 08:32) Или вам ...   Oct 15 2008, 08:09
|- - dxp   Цитата(Stas633 @ Oct 15 2008, 15:09) В пр...   Oct 15 2008, 11:59
|- - Stas633   Цитата(dxp @ Oct 15 2008, 15:59) Словом, ...   Oct 15 2008, 12:22
|- - IgorKossak   Цитата(dxp @ Oct 15 2008, 14:59) Почему н...   Oct 15 2008, 16:10
|- - ?ELF   Цитата(dxp @ Oct 15 2008, 17:59) ... ... ...   Oct 17 2008, 20:18
- - alexander55   Цитата(Stas633 @ Oct 14 2008, 01:44) Ту...   Oct 15 2008, 05:19
- - IgorKossak   Цитата(Stas633 @ Oct 14 2008, 00:44) Вопр...   Oct 15 2008, 08:38
- - Stas633   Ув. bookevg, Вы, безусловно, во многом правы! ...   Nov 24 2008, 22:08


Reply to this topicStart new topic
1 чел. читают эту тему (гостей: 1, скрытых пользователей: 0)
Пользователей: 0

 


RSS Текстовая версия Сейчас: 23rd July 2025 - 06:00
Рейтинг@Mail.ru


Страница сгенерированна за 0.01513 секунд с 7
ELECTRONIX ©2004-2016