crossplatform.ru

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


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

Введите в поле код из 6 символов, отображенных в виде изображения. Если вы не можете прочитать код с изображения, нажмите на изображение для генерации нового кода.
 

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


Последние 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 Текстовая версия Сейчас: 29.3.2024, 3:34