Наши проекты:
Журнал · Discuz!ML · Wiki · DRKB · Помощь проекту |
||
ПРАВИЛА | FAQ | Помощь | Поиск | Участники | Календарь | Избранное | RSS |
[3.145.130.31] |
|
Сообщ.
#1
,
|
|
|
Добрый день
Есть два класса работающие вместе общими глобальными переменными. Хочу объединить все вместе в отдельный класс в том числе и переменные. Возникла проблема подклассы не видят у себя внутри этих переменные. Пример. До: int a,b,c,d; - глобальные переменные class Tx; - использует глобальные переменные class Ty; - использует глобальные переменные После: My class { private: int a,b,c,d; public: Tx x; Ty y; } Какие будут идеи? |
Сообщ.
#2
,
|
|
|
Цитата mishapk @ Какие будут идеи? Не видят, потому что они у тебя private. Сделай protected. И, эти глобальные переменные разве не должны быть static? |
Сообщ.
#3
,
|
|
|
Не видят так как подклассы реализуются за пределами класса и они их просто не видят.
Сделал подклассы вложенными, тоже не видят. В Java это вроде возможно а в С++ нет. Остается только через указатели в конструкторе подклассов передавать в виде структуры. Я так думаю. |
Сообщ.
#4
,
|
|
|
Некрасивый вариант:
#include <iostream> using namespace std; class Tx; class Ty; class Config { private: int a = 2, b = 3; friend Tx; friend Ty; }; class Tx { public: int GetA(Config &r) { return r.a; } }; class Ty { public: int GetB(Config &r) { return r.b*2; } }; class Result { public: Config c; Tx x; Ty y; }; int main() { Result R; cout << R.x.GetA(R.c) << endl; cout << R.y.GetB(R.c) << endl; return 0; } |
Сообщ.
#5
,
|
|
|
Цитата mishapk @ Есть два класса работающие вместе общими глобальными переменными. Надо глобальные переменные обернуть классом. Сделать их "public" и "static". Таким образом, любой экземпляр такого класса станет объектом доступа к "глобальным" переменным. |
Сообщ.
#6
,
|
|
|
Ну да, в том числе и для этого придумали синглтоны.
|
Сообщ.
#7
,
|
|
|
Цитата JoeUser @ Ну да, в том числе и для этого придумали синглтоны. Нет, этого не нужно в данном случае. Экземпляров класса может быть любое количество, в этом и удобство. Экземпляр такого класса - это как-бы окошко многоквартирного дома. Каждое из которого выходит на один и тот же двор, и из каждого можно наблюдать одну и ту же картину. И есть возможность кинуть бутылку в одно и то же место. А из той квартиры, где этого окошка нет - дворика не видно. |
Сообщ.
#8
,
|
|
|
Цитата ЫукпШ @ Экземпляров класса может быть любое количество, в этом и удобство. А так неудобно? См Test1Class и Test2Class: #include <iostream> using namespace std; //////////////////////////////////////////////////////////////////////////////////////// template<typename T> struct Holder { Holder() { std::cout << "Holder()::Holder()" << std::endl; if (!Self) Self = new T(); Self->Init(); } ~Holder() { if (Self) { Self->Cleanup(); delete Self; std::cout << "~Holder()::Holder()" << std::endl; } } T* Self = nullptr; }; //////////////////////////////////////////////////////////////////////////////////////// template <typename T> class Singleton { public: static T* Instance() { std::cout << "Singlton::Instance()" << std::endl; static Holder<T> Dummy; return Dummy.Self; } private: Singleton() = delete; Singleton(Singleton const&) = delete; Singleton& operator= (Singleton const&) = delete; Singleton(Singleton const&&) = delete; Singleton& operator= (Singleton const&&) = delete; }; class Global { public: int GetA() { cout << "GetA" << endl; return x-1; } int GetB() { cout << "GetB" << endl; return x+1; } void Init() {}; void Cleanup() {}; private: int x = 1; }; struct Test1Class { void Print() { cout << Singleton<Global>::Instance()->GetA() << endl; } }; struct Test2Class { void Print() { cout << Singleton<Global>::Instance()->GetB() << endl; } }; int main() { Test1Class T1; Test2Class T2; T1.Print(); T2.Print(); return 0; } |
Сообщ.
#9
,
|
|
|
Цитата JoeUser @ Цитата ЫукпШ @ Экземпляров класса может быть любое количество, в этом и удобство. А так неудобно? См Test1Class и Test2Class: Лично мне - нет. Зачем мне дополнительные сущности для достижения той-же цели ? Достаточно описать переменную как "static". |
Сообщ.
#10
,
|
|
|
Цитата ЫукпШ @ Зачем мне дополнительные сущности для достижения той-же цели ? Достаточно описать переменную как "static". В моей реализации переменные получат гарантированно-правильную инициализацию (и освобождение) ресурсов до использования - методы Init и Cleanup. В твоем случае нужно заботиться в предметном коде о недопущении использования до инициализации этих самых бывших "глобальных" переменных нужными значениями, а не полученными по-умолчанию. ИМХО, это аргумент. |
Сообщ.
#11
,
|
|
|
Цитата JoeUser @ private: Singleton() = delete; Singleton(Singleton const&) = delete; Singleton& operator= (Singleton const&) = delete; Singleton(Singleton const&&) = delete; Singleton& operator= (Singleton const&&) = delete; Их нужно в секцию public перенести. Не по феншую, когда удаленные мемберы в закрытой секции. В противном случае ты можешь получить невнятную ошибку компиляции, и сидеть гадать почему так. А вместо класса Holder думаю имеет смысл использовать shared_ptr, или лучше вообще уйти от указателей и возвращать ссылку на статический член класса(Синглтон Майерса.). А то у тебя код для двух статический переменных неоправданно навороченный. Добавлено Цитата JoeUser @ class Global { public: int GetA() { cout << "GetA" << endl; return x-1; } int GetB() { cout << "GetB" << endl; return x+1; } void Init() {}; void Cleanup() {}; private: int x = 1; }; А этот класс я бы вообще выкинул, в нем нет никакого смысла. |
Сообщ.
#12
,
|
|
|
Цитата Wound @ Их нужно в секцию public перенести. Не по феншую, когда удаленные мемберы в закрытой секции. В противном случае ты можешь получить невнятную ошибку компиляции, и сидеть гадать почему так. Возможно. Но лучше поэксперементировать и посмотреть мой вариант и твой. Цитата Wound @ А вместо класса Holder думаю имеет смысл использовать shared_ptr, или лучше вообще уйти от указателей и возвращать ссылку на статический член класса(Синглтон Майерса.). А то у тебя код для двух статический переменных неоправданно навороченный. Давай твой вариант для коллекции |
Сообщ.
#13
,
|
|
|
Цитата JoeUser @ Возможно. Но лучше поэксперементировать и посмотреть мой вариант и твой. В смысле поэкспериментировать? Дело в том, что когда ты пишешь = delete, то компилятор выбрасывает этот член класса. И если вдруг ты его юзнул - тебе он так и скажет, такоой метод помечен как удаленный, так что вызывай другой. А когда ты его делаешь закрытым, то вполне можешь выхватить ошибку аля: не могу вызвать такой метод, он находится в секции private. Когда речь идет о небольшой логике - никаких проблем не будет. Но вдруг если будет что то понавороченее, например с какими нибудь итераторами внутри second/first или еще чего, которые нужно будет куда нибудь перенести или скопировать, то можешь потратить много времени, на выявление ошибок. Цитата JoeUser @ Давай твой вариант для коллекции Тебе какой именно? С Синглтоном? ну хорошо, щас что нибудь напишу. |
Сообщ.
#14
,
|
|
|
Цитата Wound @ А этот класс я бы вообще выкинул, в нем нет никакого смысла. Это класс из которого "фабрика синглтонов" class Singlеton, собственно, и делает синглтон В этом классе и хранятся заветные "глобальные" переменные. Низя это выкидывать. |
Сообщ.
#15
,
|
|
|
А вот интересно, как этот механизм инициализации статических переменных реализуется внутри. Где-то видел в листинге такой вариант - компилятор создает скрытую "совсем-совсем статическую" переменную, которая обнуляется вместе с .bss, после чего при каждом входе в функцию проверяет ее на равенство нулю и, если она ноль, инициализирует явную статическую переменную.
Мое чувство прекрасного сильно страдает от того, что явная переменная фактически дублирует неявную и что все эти действия реально нужны только один раз при запуске программы, но продолжают выполняться и отжирать процессорное время и электричество в течении всего времени выполнения программы. |
Сообщ.
#16
,
|
|
|
Цитата Wound @ В смысле поэкспериментировать? Дело в том, что когда ты пишешь = delete, то компилятор выбрасывает этот член класса. И если вдруг ты его юзнул - тебе он так и скажет, такоой метод помечен как удаленный, так что вызывай другой. А когда ты его делаешь закрытым, то вполне можешь выхватить ошибку аля: не могу вызвать такой метод, он находится в секции private. Когда речь идет о небольшой логике - никаких проблем не будет. Но вдруг если будет что то понавороченее, например с какими нибудь итераторами внутри second/first или еще чего, которые нужно будет куда нибудь перенести или скопировать, то можешь потратить много времени, на выявление ошибок. Проверил сообщения. Для public секции: prog.cpp: In function ‘int main()’: prog.cpp:10:5: error: use of deleted function ‘A::A()’ A a; ^ prog.cpp:6:5: note: declared here A() = delete; ^ Для private секции: prog.cpp: In function ‘int main()’: prog.cpp:10:5: error: ‘A::A()’ is private within this context A a; ^ prog.cpp:6:5: note: declared private here A() = delete; ^ Может ты и прав. Но пока я существенного не замечаю. Может потом... Добавлено Цитата Wound @ А вместо класса Holder думаю имеет смысл использовать shared_ptr, Класс Holder обеспечивает автоматическую инициализацию после создания экземпляра класса, и автоматическую очистку перед разрушением экземпляра класса. Это некое подобие функционала из Дэлфи (линк). |
Сообщ.
#17
,
|
|
|
Ну вот так наверное как то:
template<typename T> struct Singleton { private: Singleton() = default; ~Singleton() = default; public: Singleton(const Singleton&) = delete; Singleton& operator= (const Singleton&) = delete; Singleton(Singleton&&) = delete; Singleton& operator= (Singleton&&) = delete; static Singleton& Instance() { static Singleton<T> instance; return instance; } T Value() const { return Singleton<T>::Instance().m_value; } T& Value() { return Singleton<T>::Instance().m_value; } private: T m_value; }; class A { public: void print() { std::cout << "A" << std::endl; } }; class B { public: void print() { std::cout << "B" << std::endl; } }; int main() { Singleton<A>& instA = Singleton<A>::Instance(); Singleton<B>& instB = Singleton<B>::Instance(); instA.Value().print(); instB.Value().print(); std::cin.get(); return 0; } Это если конкретно через синглтон. Добавлено Цитата JoeUser @ Может ты и прав. Но пока я существенного не замечаю. Может потом... Ну ты на всех компиляторах проверил? А то например в 2017 студии пишет: 1>e:\develop\main.cpp(178): error C2248: 'C::C': cannot access private member declared in class 'C' 1>e:\develop\main.cpp(172): note: see declaration of 'C::C' 1>e:\develop\main.cpp(169): note: see declaration of 'C' Вот для вызова конструктора для такого класса: class C { private: C() = delete; }; В других компиляторах может быть иначе. Но я не вижу вообще никакого здавого смысла делать приватными удаляемые члены. Профита вообще 0. А вот если привыкнуть делать их открытыми, то профита куда больше. Цитата JoeUser @ Класс Holder обеспечивает автоматическую инициализацию после создания экземпляра класса, и автоматическую очистку перед разрушением экземпляра класса. Это некое подобие функционала из Дэлфи (линк). Ничего он там не обеспечивает. Он накладывает ограничения на используемый класс. Вообще в С++ все эти действия делаеются в конструкторе/деструкторе. А для умных указателей shared_/unique/weak можно передать функцию deleter, если тебе нужно как то по особому очистить ресурс. |
Сообщ.
#18
,
|
|
|
Цитата Wound @ Это если конкретно через синглтон. Вариант рабочий, но ИМХО, по ТЗ - не то. Топикстартеру нужно все глобальные переменные инкапсулировать в один класс, и потом дать к ним доступ из других классов. По твоему примеру это - в классах A и В должен быть доступ к таким переменным. А там пока только печать константной строки. |
Сообщ.
#19
,
|
|
|
Цитата Wound @ Ничего он там не обеспечивает. Ну не тупи Holder() { std::cout << "Holder()::Holder()" << std::endl; if (!Self) Self = new T(); Self->Init(); // <----------------------------------------- инициализация ПОСЛЕ создания а не ВО ВРЕМЯ } ~Holder() { if (Self) { Self->Cleanup(); // < ----------------------------------- очистка ДО начала процесса разрушения delete Self; std::cout << "~Holder()::Holder()" << std::endl; } } Умным указателям, как я понял, можно передать ТОЛЬКО "удалитель". Добавлено Киля, чтобы было понятно - напомню откуда "ноги растут" в моем коде. В С++ в конструкторе нельзя вызывать виртуальные функции. Таким образом только деструктор может быть виртуальным. Мой код обеспечивает функционал "виртуального конструктора". Как-то так. Добавлено Цитата Wound @ Ну ты на всех компиляторах проверил? А то например в 2017 студии пишет: Если честно, я еще ни одной программы не скомпилировал в студии. Потому, что ее у меня нет. Хватает GCC и clang. Кстати, вот что пишет clang для ПРИВАТНОЙ секции: prog.cc:10:5: error: call to deleted constructor of 'A' A a; ^ prog.cc:6:5: note: 'A' has been explicitly marked deleted here A() = delete; ^ 1 error generated. Выкинь студию! |
Сообщ.
#20
,
|
|
|
Цитата JoeUser @ Ну не тупи Попробуй передать в свой Holder класс у которого нет Init и Cleanup, и ты поймешь о чем я. Цитата JoeUser @ Топикстартеру нужно все глобальные переменные инкапсулировать в один класс, и потом дать к ним доступ из других классов. И в чем проблема? Получай на здоровье, например так: template<typename T> struct Singleton { private: Singleton() = default; ~Singleton() = default; public: Singleton(const Singleton&) = delete; Singleton& operator= (const Singleton&) = delete; Singleton(Singleton&&) = delete; Singleton& operator= (Singleton&&) = delete; static Singleton& Instance() { static Singleton<T> instance; return instance; } T Value() const { return Singleton<T>::Instance().m_value; } T& Value() { return Singleton<T>::Instance().m_value; } private: T m_value; }; class A { public: void print() { std::cout << "A: " << a << std::endl; } int a; }; class B { public: void print() { std::cout << "B: " << b << std::endl; } int b; }; class C { public: void DoSomething() { Singleton<A>& instA = Singleton<A>::Instance(); Singleton<B>& instB = Singleton<B>::Instance(); instA.Value().print(); instB.Value().print(); } }; int main() { Singleton<A>& instA = Singleton<A>::Instance(); Singleton<B>& instB = Singleton<B>::Instance(); instA.Value().a = 10; instB.Value().b = 20; instA.Value().print(); instB.Value().print(); std::cout << "-------C---------" << std::endl; C c; c.DoSomething(); std::cin.get(); return 0; } Это же синглентон, где хочешь там и вызывай его. У тебя гарантированно будет 1 экземпляр класса. |
Сообщ.
#21
,
|
|
|
Цитата Wound @ Попробуй передать в свой Holder класс у которого нет Init и Cleanup, и ты поймешь о чем я. Так это же специально и сделано было для этого! |
Сообщ.
#22
,
|
|
|
Цитата JoeUser @ Умным указателям, как я понял, можно передать ТОЛЬКО "удалитель". Cоздатель, ВНЕЗАПНО, вызывается в момент конструирования указателя. Что целиком и полностью удовлетворяет идиоме RAII. Цитата JoeUser @ Киля, чтобы было понятно - напомню откуда "ноги растут" в моем коде. В С++ в конструкторе нельзя вызывать виртуальные функции. Таким образом только деструктор может быть виртуальным. Мой код обеспечивает функционал "виртуального конструктора". Как-то так. Твой код накладывает ограничение на использование объектов разных типов. Что если мне нужно передать в твой Holder shared_ptr объект? Цитата JoeUser @ Если честно, я еще ни одной программы не скомпилировал в студии. Потому, что ее у меня нет. Хватает GCC и clang. Кстати, вот что пишет clang для ПРИВАТНОЙ секции: Речь идет не о конкретно студии. Речь идет о хорошем стиле программирования. Писать удаленные методы в приватной секции не по феншую. Понимаешь? Добавлено Цитата JoeUser @ Так это же специально и сделано было для этого! Зачем? Что бы постоянно городить обертки с пустыми Init и Cleanup? |
Сообщ.
#23
,
|
|
|
Цитата Wound @ И в чем проблема? Проблема в том, что эти переменные "а" и "b" должны хранится вне классов A и B. Ну прочти самое первое сообщение топикстартера |
Сообщ.
#24
,
|
|
|
Цитата JoeUser @ Проблема в том, что эти переменные "а" и "b" должны хранится вне классов A и B. Если ты еще не понял, то эти классы A и B и есть переменные, которые должны храниться вне этих классов. Попробуй выкинуть классы A и B. Если тебе нужны примитивные типы, создай структуру с нужным количеством членов и передай в синглтон. Все. |
Сообщ.
#25
,
|
|
|
Цитата Wound @ Попробуй передать в свой Holder класс у которого нет Init и Cleanup, и ты поймешь о чем я. Тут ничего страшного. В принципе можно еще шаблонами поиграться, чтобы на этапе компиляции вырезать вызовы. Лениво. Я уповаю на оптимизатор - их и так там не будет. Цитата Wound @ Если ты еще не понял, то эти классы A и B и есть переменные, которые должны храниться вне этих классов. Попробуй выкинуть классы A и B. Если тебе нужны примитивные типы, создай структуру с нужным количеством типов и передай в синглтон. Все. Просто сделай как просит топикстартер Добавлено Цитата Wound @ Cоздатель, ВНЕЗАПНО, вызывается в момент конструирования указателя. Это не гибко. Я уже писал выше о невозможности сделать штатными средствами виртуальное конструирование. |
Сообщ.
#26
,
|
|
|
Цитата JoeUser @ Тут ничего страшного. В принципе можно еще шаблонами поиграться, чтобы на этапе компиляции вырезать вызовы. Лениво. Я уповаю на оптимизатор - их и так там не будет. А то, что тебе каждый раз придется делать обертки над типами, у которых нет этих методов - тебя не смущает? Цитата JoeUser @ Просто сделай как просит топикстартер Он просит чтоб было вот так, как я понял? Цитата mishapk @ Пример. До: int a,b,c,d; - глобальные переменные class Tx; - использует глобальные переменные class Ty; - использует глобальные переменные После: Myclass { private: int a,b,c,d; public: Tx x; Ty y; } Какие будут идеи? В такой постановке задачи, я сделаю соответствующие конструкторы у классов Tx/Ty И передам нужные переменные из класса MyClass Добавлено Цитата JoeUser @ Это не гибко. Я уже писал выше о невозможности сделать штатными средствами виртуальное конструирование. Че это не гибко? А вызывать Init и Cleanup гибко? Конструктор/Деструктор вроде как раз их и заменяют, не? |
Сообщ.
#27
,
|
|
|
Цитата Wound @ В такой постановке задачи, я сделаю соответствующие конструкторы у классов Tx/Ty И передам нужные переменные из класса MyClass По секрету: там будет 128 переменных! Цитата Wound @ А то, что тебе каждый раз придется делать обертки над типами, у которых нет этих методов - тебя не смущает? Можно предусмотреть базовый класс с пустыми вызовами, а в наследниках про эти функции забыть. Элементарно, Ватсон! Цитата Wound @ Конструктор/Деструктор вроде как раз их и заменяют, не? Напоминаю! В конструкторе нельзя вызывать виртуальные функции. В моем коде - это решается. |
Сообщ.
#28
,
|
|
|
Цитата JoeUser @ По секрету: там будет 128 переменных! Тогда я объявлю массив и передам массив. Если у меня куча классов, где эти переменные нужны, создам структуру, как я тебе писал выше и передам ее в синглтон. Структуру написать? Ок struct MyType { int variable1; shared_ptr<int> variable2; MyObject variable3; std::vector<some type> variable4; ololo variable5; int variable6; int variable7; ... }; .. auto& gVar = Singlenton<MyType>::Instance(); gVar.Value().bla bla bla Цитата JoeUser @ Можно предусмотреть базовый класс с пустыми вызовами, а в наследниках про эти функции забыть. Элементарно, Ватсон! Ну вот я захотел передать в твой холдер std::shared_ptr<A> че мне делать то? Цитата JoeUser @ Напоминаю! В конструкторе нельзя вызывать виртуальные функции. В моем коде - это решается. А зачем это нужно то? Я что сам не могу вызвать Init/Cleanup, если мне понадобиться? А что если у меня Cleanup может генерировать исключение? Выходят я получу граблями в лоб из за твоего мега кода? |
Сообщ.
#29
,
|
|
|
Цитата Wound @ Тогда я объявлю массив и передам массив. Блин Ну так твой MyType и есть мой Global !!! Цитата Wound @ Ну вот я захотел передать в твой холдер std::shared_ptr<A> че мне делать то? Не пробовал, не знаю. Заверни его в структуру или класс и передай. Надо пробовать. Цитата Wound @ А зачем это нужно то? Я что сам не могу вызвать Init/Cleanup, если мне понадобиться? А можешь и забыть. А ненаследованный класс тебя заставит не забыть. Цитата Wound @ Подавляй. Считай - это полноценная часть деструктора. В деструкторе же ты не собираешься бросать исключения? Или собираешься? А что если у меня Cleanup может генерировать исключение? Выходят я получу граблями в лоб из за твоего мега кода? |
Сообщ.
#30
,
|
|
|
Цитата JoeUser @ Блин Ну так твой MyType и есть мой Global !!! Нет, у меня MyType - это структура это отдельный тип, который агрегирует в себе 7 переменных разных типов, и передается в синглентон. У тебя твой Holder может принять ровно 1 объект одного типа, и зачем то вызывает для него Init в конструкторе и Cleanup в деструкторе. Моя структура чем то отдаленно похожа на твой класс Global, и то я не уверен в этом. Цитата JoeUser @ Не пробовал, не знаю. Заверни его в структуру или класс и передай. Надо пробовать. Так я тебе скажу - оно не скомпилируется. А потом, если допустим даже предположить, что я завернул свой shared_ptr в класс и определил там методы Init и Cleanup - то даже в этом случае твой код небезопасен в плане исключений, потому как не дай бог у меня внутри функции Init что то понасоздается, а потом вдруг произойдет исключение в ней же. Все, каюк утечка ресурсов обеспечена. Цитата JoeUser @ А можешь и забыть. А ненаследованный класс тебя заставит не забыть. Я так не пишу, соответственно и забывать мне нечего. Твой код не удовлетворяет RAII, соответственно он не безопасный. Цитата JoeUser @ Подавляй. Считай - это полноценная часть деструктора. В деструкторе же ты не собираешься бросать исключения? Или собираешься? Дело в том, что деструктор - это часть языковой конструкции класса, поведение которой четко оговорено, и я знаю что от него ожидать или нет. А твой метод Cleanup - ни к селу ни к городу. Добавлено Во, попробовал поиграться с твоим кодом, выхватил по щам в рантайме: https://ideone.com/VP5Y8i #include <iostream> #include <memory> template<typename T> struct Holder { Holder() { std::cout << "Holder()::Holder()" << std::endl; if (!Self) Self = new T(); Self->Init(); } ~Holder() { if (Self) { Self->Cleanup(); delete Self; std::cout << "~Holder()::Holder()" << std::endl; } } T* Self = nullptr; }; class SomeClass { public: void Init(){} void Cleanup() {} int member; }; //////////////////////////////////////////////////////////////////////////////////////// template <typename T> class Singleton { public: static T* Instance() { std::cout << "Singlton::Instance()" << std::endl; static Holder<T> Dummy; return Dummy.Self; } private: Singleton() = delete; Singleton(Singleton const&) = delete; Singleton& operator= (Singleton const&) = delete; Singleton(Singleton const&&) = delete; Singleton& operator= (Singleton const&&) = delete; }; int main() { { auto pInst = Singleton<SomeClass>::Instance(); pInst->member = 10; std::cout << pInst->member << std::endl; std::unique_ptr<SomeClass> pObj(pInst); } auto pInst = Singleton<SomeClass>::Instance(); pInst->member = 20; return 0; } *** Error in `./prog': double free or corruption (fasttop): 0x0000557abbacbc30 *** ======= Backtrace: ========= /lib/x86_64-linux-gnu/libc.so.6(+0x70bcb)[0x2ba3cbcb8bcb] /lib/x86_64-linux-gnu/libc.so.6(+0x76f96)[0x2ba3cbcbef96] /lib/x86_64-linux-gnu/libc.so.6(+0x7778e)[0x2ba3cbcbf78e] ./prog(+0xe77)[0x557ab9b48e77] /lib/x86_64-linux-gnu/libc.so.6(+0x35920)[0x2ba3cbc7d920] /lib/x86_64-linux-gnu/libc.so.6(+0x3597a)[0x2ba3cbc7d97a] /lib/x86_64-linux-gnu/libc.so.6(__libc_start_main+0xf8)[0x2ba3cbc682b8] ./prog(+0xd4a)[0x557ab9b48d4a] ======= Memory map: ======== 2ba3caf68000-2ba3caf8b000 r-xp 00000000 fd:00 2840974 /lib/x86_64-linux-gnu/ld-2.24.so 2ba3caf8b000-2ba3caf8f000 rw-p 00000000 00:00 0 2ba3caf98000-2ba3caf9d000 rw-p 00000000 00:00 0 2ba3cb18b000-2ba3cb18c000 r--p 00023000 fd:00 2840974 /lib/x86_64-linux-gnu/ld-2.24.so 2ba3cb18c000-2ba3cb18d000 rw-p 00024000 fd:00 2840974 /lib/x86_64-linux-gnu/ld-2.24.so 2ba3cb18d000-2ba3cb18e000 rw-p 00000000 00:00 0 2ba3cb18e000-2ba3cb300000 r-xp 00000000 fd:00 2967755 /usr/lib/x86_64-linux-gnu/libstdc++.so.6.0.22 2ba3cb300000-2ba3cb500000 ---p 00172000 fd:00 2967755 /usr/lib/x86_64-linux-gnu/libstdc++.so.6.0.22 2ba3cb500000-2ba3cb50a000 r--p 00172000 fd:00 2967755 /usr/lib/x86_64-linux-gnu/libstdc++.so.6.0.22 2ba3cb50a000-2ba3cb50c000 rw-p 0017c000 fd:00 2967755 /usr/lib/x86_64-linux-gnu/libstdc++.so.6.0.22 2ba3cb50c000-2ba3cb510000 rw-p 00000000 00:00 0 2ba3cb510000-2ba3cb613000 r-xp 00000000 fd:00 2841003 /lib/x86_64-linux-gnu/libm-2.24.so 2ba3cb613000-2ba3cb812000 ---p 00103000 fd:00 2841003 /lib/x86_64-linux-gnu/libm-2.24.so 2ba3cb812000-2ba3cb813000 r--p 00102000 fd:00 2841003 /lib/x86_64-linux-gnu/libm-2.24.so 2ba3cb813000-2ba3cb814000 rw-p 00103000 fd:00 2841003 /lib/x86_64-linux-gnu/libm-2.24.so 2ba3cb814000-2ba3cb82a000 r-xp 00000000 fd:00 2840941 /lib/x86_64-linux-gnu/libgcc_s.so.1 2ba3cb82a000-2ba3cba29000 ---p 00016000 fd:00 2840941 /lib/x86_64-linux-gnu/libgcc_s.so.1 2ba3cba29000-2ba3cba2a000 r--p 00015000 fd:00 2840941 /lib/x86_64-linux-gnu/libgcc_s.so.1 2ba3cba2a000-2ba3cba2b000 rw-p 00016000 fd:00 2840941 /lib/x86_64-linux-gnu/libgcc_s.so.1 2ba3cba2b000-2ba3cba43000 r-xp 00000000 fd:00 2840960 /lib/x86_64-linux-gnu/libpthread-2.24.so 2ba3cba43000-2ba3cbc42000 ---p 00018000 fd:00 2840960 /lib/x86_64-linux-gnu/libpthread-2.24.so 2ba3cbc42000-2ba3cbc43000 r--p 00017000 fd:00 2840960 /lib/x86_64-linux-gnu/libpthread-2.24.so 2ba3cbc43000-2ba3cbc44000 rw-p 00018000 fd:00 2840960 /lib/x86_64-linux-gnu/libpthread-2.24.so 2ba3cbc44000-2ba3cbc48000 rw-p 00000000 00:00 0 2ba3cbc48000-2ba3cbddd000 r-xp 00000000 fd:00 2841097 /lib/x86_64-linux-gnu/libc-2.24.so 2ba3cbddd000-2ba3cbfdc000 ---p 00195000 fd:00 2841097 /lib/x86_64-linux-gnu/libc-2.24.so 2ba3cbfdc000-2ba3cbfe0000 r--p 00194000 fd:00 2841097 /lib/x86_64-linux-gnu/libc-2.24.so 2ba3cbfe0000-2ba3cbfe2000 rw-p 00198000 fd:00 2841097 /lib/x86_64-linux-gnu/libc-2.24.so 2ba3cbfe2000-2ba3cbfe6000 rw-p 00000000 00:00 0 2ba3cc000000-2ba3cc021000 rw-p 00000000 00:00 0 2ba3cc021000-2ba3d0000000 ---p 00000000 00:00 0 557ab9b48000-557ab9b4a000 r-xp 00000000 fd:00 23353346 /home/g1NiFf/prog 557ab9d49000-557ab9d4a000 r--p 00001000 fd:00 23353346 /home/g1NiFf/prog 557ab9d4a000-557ab9d4b000 rw-p 00002000 fd:00 23353346 /home/g1NiFf/prog 557abbab9000-557abbaeb000 rw-p 00000000 00:00 0 [heap] 7fff4aec3000-7fff4aee4000 rw-p 00000000 00:00 0 [stack] 7fff4afee000-7fff4aff0000 r-xp 00000000 00:00 0 [vdso] 7fff4aff0000-7fff4aff2000 r--p 00000000 00:00 0 [vvar] ffffffffff600000-ffffffffff601000 r-xp 00000000 00:00 0 [vsyscall] Это я еще не генерировал исключение в Init. |
Сообщ.
#31
,
|
|
|
Цитата Wound @ метод Cleanup - ни к селу ни к городу. A добавлю в описалово noexcept - только попробуй выбросить необработанное исключение Цитата Wound @ Твой код не удовлетворяет RAII В каком месте кода? |
Сообщ.
#32
,
|
|
|
Цитата JoeUser @ A добавлю в описалово noexcept - только попробуй выбросить необработанное исключение В Init тоже добавишь? Цитата JoeUser @ В каком месте кода? Везде. Вот например, лови: template<typename T> struct Holder { Holder() { std::cout << "Holder()::Holder()" << std::endl; if (!Self) Self = new T(); Self->Init(); } ~Holder() { if (Self) { Self->Cleanup(); delete Self; std::cout << "~Holder()::Holder()" << std::endl; } } T* Self = nullptr; }; //////////////////////////////////////////////////////////////////////////////////////// template <typename T> class Singleton { public: static T* Instance() { std::cout << "Singlton::Instance()" << std::endl; static Holder<T> Dummy; return Dummy.Self; } private: Singleton() = delete; Singleton(Singleton const&) = delete; Singleton& operator= (Singleton const&) = delete; Singleton(Singleton const&&) = delete; Singleton& operator= (Singleton const&&) = delete; }; class SomeClass { public: void Init() { connect(); initialize(); } void Cleanup() { disconnect(); } void connect() { std::cout << "connect" << std::endl; } void disconnect() { std::cout << "disconnect" << std::endl; } void initialize() { std::cout << "initialize" << std::endl; throw "Aaaaaaaaaaaaaaaaa"; } int member; }; int main() { { auto pInst = Singleton<SomeClass>::Instance(); pInst->member = 10; std::cout << pInst->member << std::endl; } auto pInst = Singleton<SomeClass>::Instance(); pInst->member = 20; return 0; } Добавлено Вот: https://ideone.com/8l75us Потерял ресурс, выхватил дедлок, не закрыл соединение, получил мемори лик... |
Сообщ.
#33
,
|
|
|
Цитата Wound @ Во, попробовал поиграться с твоим кодом, выхватил по щам в рантайме: Ваще ниче не понял в твоей задумке! Но это жесть ... Я бы еще разделил на нуль для надежности !!! Добавлено Цитата Wound @ В Init тоже добавишь? Надо и в Инит добавлять |
Сообщ.
#34
,
|
|
|
Цитата JoeUser @ Ваще ниче не понял в твоей задумке! Но это жесть ... Я бы еще разделил на нуль для надежности !!! Ну ты из синглтона возвратил указатель на класс, я же могу его передать куда нибудь дальше в функцию? Например, что мешает мне написать вот так: void SomeFunction(std::unique_ptr<SomeClass>&& obj) { } int main() { std::unique_ptr<SomeClass> pObj(Singleton<SomeClass>::Instance()); SomeFunction(std::move(pObj)); } ?? И выхватить исключение? Цитата JoeUser @ Надо и в Инит добавлять А зачем? В конструкторах что исключения плохо бросать? А если мне нужно кинуть в Init исключение? Что мне делать то? |
Сообщ.
#35
,
|
|
|
Ребят, вы в Холивары не хотите переехать? Бо как ТС спросил вас, как ему сложить три сущности, а вы втираете ему про алгебру Ли и разбираете разницы гомоморфизмов своих разных методов сложения.
|
Сообщ.
#36
,
|
|
|
Ну можно и в холивары, я не против.
|
Сообщ.
#37
,
|
|
|
Скрытый текст Цитата Qraizer @ Ребят, вы в Холивары не хотите переехать? Цитата Wound @ Ну можно и в холивары, я не против. Не, я пожалуй пойду выпью чаю и съем еще французских булочек Киля - победил. |