Класс Static и Normal объединены в одном классе - PullRequest
2 голосов
/ 16 февраля 2012

Я изо всех сил пытаюсь объяснить ситуацию.Надеюсь, то, что я написал, понятно.У нас уже есть класс, определенный как

public ref class TestClass
{       
public:
        TestClass();
        virtual ~TestClass();
protected:              
        Car* m_car;

}

TestClass управляемый C ++ и Car неуправляемый C ++.

Пока все хорошо, но теперь мне нужно сделать статический объект из TestClass также.Поэтому я изменяю код, как показано ниже

public ref class TestClass 
{
private:
    static  TestClass^  s_test = nullptr ;
public:
    TestClass();
    virtual ~TestClass();
    static TestClass^ Instance();
protected:              
    Car* m_car;
}

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

TestClass staticobj = TestClass::Instance();

В другом месте, просто позвоните

TestClass normalobj = gcnew TestClass();

Функция экземпляра создает s_test статический объект и возвращает его.

TestClass ^ TestClass::Instance() 
{
    if(s_test == nullptr)
    {
          s_test = gcnew TestClass();
          s_test->m_car = new Car();

    }       
    return s_test;
}

Это хороший подход?Есть ли другой лучший подход для достижения того же результата?

Редактировать: К вашему сведению Вышеприведенный код работает.

Я объединил решения Krizz и Reed Copsey.Это решает независимый синглтон и утечка памяти.Вот мой пример кода, Специальный класс Singleton, полученный из тестового класса,

    public ref class SpecialSingletonTestClass: public TestClass
        {
            private:
                static SpecialSingletonTestClass ^ s_ SpecialSingletonTestClass = nullptr;
             public:
                SpecialSingletonTestClass ();
                static SpecialSingletonTestClass ^ Instance();
        };

Изменен тестовый класс, так что теперь у него есть еще одна функция финализатора.

    public ref class TestClass 
    {
    public:
        TestClass ();
        virtual ~ TestClass ();
        ! TestClass ();
protected:              
         Car* m_car;

    }

Я тестировал выше шаблон, этоработал.

Спасибо вам, ребята,

LE

Ответы [ 3 ]

2 голосов
/ 16 февраля 2012

Это хороший подход?

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

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

Если вам действительно нужен способ иметь «глобальный» экземпляр этого класса, я бы включил его в отдельный класс, который реализует синглтон. Это, по крайней мере, дало бы понять, что вы имеете дело с чем-то, что в данном случае является единственным случаем. Я бы не совмещал оба варианта использования в одном классе.

1 голос
/ 16 февраля 2012

Ну, на самом деле есть проблема с утечками памяти в вашем коде.

Вы объявляете только virtual ~TestClass();, который для управляемых классов внутренне превращается компилятором C ++ / CLI в реализацию IDisposable.Dispose().

Поэтому, если вы введете в него delete car, он будет вызываться только в том случае, если вы delete test_class или, например, перенос в блок using (TestClass tst) {} при использовании из C #.

не будет вызываться, когда объект GCed!

Чтобы быть уверенным, что он вызывается, вам необходимо добавить финализатор в ваш класс !MyClass();, который преобразован компилятором в virtual void Finalize() и, таким образом, недетерминированно вызывается, когда GC освобождает объект.

И это единственный способ освободить m_car одноэлементного объекта.

Поэтому я предлагаю:

TestClass()
{
    m_car = new Car();
}

~TestClass()
{
    if (m_car) 
        delete m_car;
    m_car = NULL;
}

!TestClass()
{
    if (m_car) 
        delete m_car;
    m_car = NULL;
}
1 голос
/ 16 февраля 2012

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

Что касается того, что вы кодировали, товыглядит совершенно нормально.Мои единственные комментарии: ваша функция Instance() не должна выполнять построение на Car, функция Instance() должна просто вызывать конструктор по умолчанию TestClass, который должен все это делать.

РЕДАКТИРОВАТЬ

Применительно к:

@ crush.Класс уже определен, мне просто нужно получить его статический объект.Синглтон означает только один объект класса, но в этом случае класс имеет несколько нормальных объектов.Но я хочу использовать только один объект этого класса для одной конкретной цели только в течение ограниченного периода времени.- LE 2 минуты назад

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

  1. Дизайн Singleton создан для существования в статическом стиле - переменная будет жить дляобласть вашей программы после ленивой инициализации.
  2. Разрешение глобального доступа приведет к движению вашего кода в направлении логики спагетти.Вам было бы лучше динамически выделить тот, который вам нужен, и передать указатель туда, где он вам нужен.Для этого подойдет shared_ptr.

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

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...