crossplatform.ru

Здравствуйте, гость ( Вход | Регистрация )


  Ответ в подклассы Singlton
Введите ваше имя
Подтвердите код

Введите в поле код из 6 символов, отображенных в виде изображения. Если вы не можете прочитать код с изображения, нажмите на изображение для генерации нового кода.
Теги
Выровнять по центру
Ссылка на тему
Ссылка на сообщение
Скрытый текст
Сокращение
Код с подсветкой
Offtopic
 
Удалить форматирование
Спец. элементы
Шрифт
Размер
 
Цвет шрифта
 
Отменить ввод
Вернуть ввод
Полужирный
Курсив
Подчеркнутый
 
 
Смайлики
Вставить изображение
Вставить адрес электронной почты
Цитата
Код
Раскрывающийся текст
 
Увеличить отступ
По левому краю
По центру
По правому краю
Вставить список
Вставить список

Опции сообщения
 Включить смайлы?
Иконки сообщения
(Опционально)
                                
                                
  [ Без иконки ]
 


Последние 10 сообщений [ в обратном порядке ]
wiz29 Дата 26.2.2015, 17:53
 
Цитата(call_me_Frank @ 25.2.2015, 22:40) *
Что скажете насчет такого решения?


По хорошему, как было сказано вами же выше - наличие виртуального интерфейса не обязательно, особенно, если не планируется дать возможность пользователю менять поведение одиночки.
Реализацию же, всегда можно "скрыть" от непосредственных пользователей.
Iron Bug Дата 26.2.2015, 11:21
  в случае, если перекрёстные ссылки всё-таки есть (это должны быть именно ссылки, а не объекты класса), то стандартное решение состоит в использовании предварительной декларации класса:
class ClassB;  // предварительная декларация класса ClassB

class ClassA {
     ClassB *ptrB;
};

class ClassB {
    ClassA *ptrA;
    ClassA A;  // после полного определения класса мы можем использовать не только указатели, но и объекты класса
};
lanz Дата 26.2.2015, 10:06
 
Цитата
Получаются перекрестные ссылки, и я не нашел решения, как их развязать. Что скажете, сможете предложить решение? или это я не понял ваших комментариев?

Все нормально, нет перекрестных ссылок :lol:
Раскрывающийся текст
class1.h
class Class1 {
Class1 * instance();
...
}

class1.cpp
#include "class1.h"
#include "class2.h"
Class1 * Class1::instance() {
  ...
}

class2.h
#include "class1.h"
class Class2 : public Class1 { ...}

class2.cpp
#include "class2.h"
...
call_me_Frank Дата 25.2.2015, 22:40
  Постараюсь ответить по-порядку )

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

да, согласен, решение с классами действительно получилось довольно странным. я его не буду использовать, но кое на чем хочу остановиться: как мне показалось, вы (и Iron Bug, и wiz29) не поняли моего вопроса насчет развязки хедеров. Дело в том, что нет возможности вынести class2 в отдельный файл - он зависит от class1, который в свою очередь использует class2 в своей функции instance(). Получаются перекрестные ссылки, и я не нашел решения, как их развязать. Что скажете, сможете предложить решение? или это я не понял ваших комментариев?

Цитата
не совсем понятно, зачем этот огород?

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

wiz29,
Цитата
Пользователю вообще обычно нет дела, куда пишется, был бы интерфейс, который позволяет это делать.
- именно в этом и состоит моя задача.

Цитата
Опять же, есть вариант при котором могут быть реализованы несколько объектов-одиночек.
- мне кажется, именно он и реализован во втором предложенном мной варианте с шаблонами, нет? Что скажете насчет такого решения?
wiz29 Дата 25.2.2015, 19:25
 
Цитата(call_me_Frank @ 25.2.2015, 16:17) *
именно!

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

Собственно, я не могу понять: все классы (LOGGER & FILE_LOGGER, DB_LOGGER, ...) должны быть реализованы как Singleton, или не все? если FILE_LOGGER, наследует LOGGER и в классе BASE я использую интерфейс класса LOGGER, значит надо прописать в нем виртуальную ф-ию log(QString), для того, что бы переопределить её в FILE_LOGGER. Но если класс LOGGER является Singlton'ом, то значит ф-ия log() должна быть static...вот какие противоречия роятся у меня в голове :blink:


В этом случае перечисленные (LOGGER & FILE_LOGGER, DB_LOGGER, ...) должны быть реализациями интерфейса логгирования. Пользователю вообще обычно нет дела, куда пишется, был бы интерфейс, который позволяет это делать.
Интерфейс не всегда означает присутствие виртуальных методов. В терминологии шаблонов - это просто наличие у класса определенных методов/полей.

Опять же, есть вариант при котором могут быть реализованы несколько объектов-одиночек. Каждый из которых будет выполнять свою задачу, либо вариант о котором я уже говорил: наличие некоторого "абстрактного" "устройства" вывода для отправки логов (на диск, в базу, в сеть и тп). Все зависит от целей.
Iron Bug Дата 25.2.2015, 19:11
 
Цитата(wiz29 @ 25.2.2015, 21:06) *
не совсем понятно, зачем этот огород?

это просто упражнение на технику программирования. весьма полезное, кстати.
wiz29 Дата 25.2.2015, 19:11
  не совсем понятно, зачем этот огород?
qDebug() все эти вещи решает вполне прозрачно, или любой другой подобный объект.
Вывод всегда можно направить в нужное место.

Цитата(call_me_Frank @ 25.2.2015, 17:26) *
и появился вопрос: как развязать классы по отдельным h-файлам? получается зацикленное включение хедеров


обычно так решают:
#ifndef SOMEHEADER_H
#define SOMEHEADER_H

#include <otherheader.h>

class SomeClass
{
};

#endif //SOMEHEADER_H
Iron Bug Дата 25.2.2015, 19:02
  насчёт решения с классами - какое-то оно странное. честно говоря, непонятно, как это будет использоваться. подумай ещё. это полезно. и обязательно попробуй использовать свои классы, без этого ты не поймёшь потенциальных минусов своего решения.

Цитата(call_me_Frank @ 25.2.2015, 19:26) *
и появился вопрос: как развязать классы по отдельным h-файлам? получается зацикленное включение хедеров

это стандартное решение в С/C++. каждый хэдер всегда заключён в блок препроцессорных определений:
#ifndef SOME_HEADER_NAME
#define SOME_HEADER_NAME
....
<код>
....
#endif

и ещё: лучше не использовать имена переменных, начинающиеся с двух подчёркиваний ( __ ) - часто это зарезервированные имена служебных переменных и функций и можно случайно напороться на конфликт с определениями в стандартных библиотеках.
call_me_Frank Дата 25.2.2015, 18:41
  Вот еще один вариант реализации с помощью шаблонов:

template<class T>
class SingleTonePattern {

public:
    static T& getInstance() {
        static T instance;
        return instance;
    }

    virtual void echo() = 0;
};

class CustomSingleTone : public SingleTonePattern<CustomSingleTone>
{
    friend class SingleTonePattern<CustomSingleTone>;
private:
    CustomSingleTone() {}

public:
    virtual void echo() {
       qDebug() << "ECHO!!";
    }
};


и вызов:

    CustomSingleTone &st = SingleTonePattern<CustomSingleTone>::getInstance();
    st.echo();


что скажете?
call_me_Frank Дата 25.2.2015, 17:26
  решил! 8)

// .H

#ifndef CLASS1_H
#define CLASS1_H

#include <iostream>

enum LOG_TYPE {LOG_C1 = 0, LOG_C2 = 1};

class class1;

class c1Dest
{
    class1 * _inst;
public:
    ~c1Dest();
    void init(class1 * p);
};

class class1
{
    static class1 * __inst;
    static c1Dest dest;

    static LOG_TYPE type;
protected:
    class1(){}
    class1(const class1&);
    class1& operator=(class1&);
    ~class1(){}

    friend class c1Dest;
public:
        static class1& instance();
    virtual void echo();
};

class class2 : public class1
{
public:
    void echo();
};

#endif // CLASS1_H


// .CPP

#include "class1.h"

LOG_TYPE class1::type = LOG_C1;

class1 * class1::__inst = 0;
c1Dest class1::dest;

c1Dest::~c1Dest(){
    delete _inst;
}

void c1Dest::init(class1 *p){
    _inst = p;
}

class1& class1::instance(){
    if (!__inst){
        switch (type){
            case LOG_C1: __inst = new class1; break;
            case LOG_C2: __inst = new class2; break;
        }
        dest.init(__inst);
    }
    return *__inst;
}

void class1::echo(){
    std::cout << "class1::echo() " << this << std::endl;
}

void class2::echo(){
    std::cout << "class2::echo() " << this << std::endl;
}


пригодна такая реализация? сделал, порадовался...теперь засомневался <_<

и появился вопрос: как развязать классы по отдельным h-файлам? получается зацикленное включение хедеров
Просмотр темы полностью (откроется в новом окне)
RSS Рейтинг@Mail.ru Текстовая версия Сейчас: 5.7.2025, 0:24