静态和普通类组合在一个类中

问题描述:

我正在尽力解释这种情况。我希望,我写的是可以理解的。 我们已经像类静态和普通类组合在一个类中

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(); 

实例函数正在创建静态对象并返回它。

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(); 
     }; 

改变了识别TestClass所以它有一个现在更多的终结功能。

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

    } 

我测试了上面的模式,它的工作。

谢谢你们,

L.E.

+0

您正在尝试做一个单身? – crush 2012-02-15 21:36:43

+0

@crush。该类已经定义我只需要获得它的静态对象。单例表示类只有一个对象,但在这种情况下,类有多个普通对象。但是我只想在有限的时间内只为一个特定的目标使用这个类的一个对象。 – 2012-02-15 21:42:29

+0

问题或对此代码的焦虑是什么? – Krizz 2012-02-15 21:45:36

嗯,实际上在代码中存在内存泄漏问题。

您只声明virtual ~TestClass();,对于托管类,它们由C++/CLI编译器内部转换为实现IDisposable.Dispose()

因此,如果您将delete car加入其中,则仅在您使用delete test_class或在从C#使用时,将其包装到using (TestClass tst) {}区块中。

它会不是当对象被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; 
} 
+0

这是我一直在努力的另一个问题。你的代码看起来很有希望,但是由于我的大脑处理器在非托管代码中速度很慢。我试图看看我可以如何结合@Reed Copsey的方法和你的方法来摆脱内存泄漏和类(单身或正常)的单例。感谢您的代码。 – 2012-02-15 23:01:03

+1

只需要我所描述的析构函数和终结器,然后创建另一个类'SpecialSingletonTestClass',它继承自'TestClass'并在那里放置'SpecialSingletonTestClass^getInstance()'和's_test'。 – Krizz 2012-02-15 23:04:40

这是一个很好的方法吗?

我可能不会认为这是一个好方法,因为您正在创建一个单独的类,您可以直接实例化一个单例类和一个普通类。

通常,如果你需要一个单例,这将排除需要或希望能够实例化类。

如果你真的需要有一个方法来获得这个类的“全局”实例,我会将它封装在一个单独的类中实现单例。这至少可以清楚地表明,你正在处理的是那种情况下的单个实例。我不会将两种用例混合到一个类中。

+0

不在一个类中混合两种情况是正确的。这可能会起作用,但为此我必须创建使用当前类的Singleton类。这在我的情况下是不可取的。 – 2012-02-15 22:00:29

+0

@ L.E。如果你真的需要一个单例实例,那将是我的方法。把这个混合到同一个类中真是令人难以置信的事情。也许只是有一个单独的类,它有你的类的单个实例(静态)? – 2012-02-15 22:03:09

我不确定在什么情况下可能会需要同一类的单例风格的语义和正常的创建语义。

就你所编码的而言,它看起来完全没问题。我唯一的意见是你的Instance()函数不需要在Car上执行构造,Instance()函数应该只调用TestClass的默认构造函数,它应该完成所有这些工作。

EDIT

在参考:

@crush。该类已经定义我只需要获得它的静态对象。单例表示类只有一个对象,但在这种情况下,类有多个普通对象。但是我只想在有限的时间内只为一个特定的目标使用这个类的一个对象。 - L.E. 2分钟前

一个单身人士(通常)是一个坏设计的标志 - 很多人实际上称它为反模式。机会是,如果你只需要这一类的有限时间内的这一个单一的特定情况下有一些问题:

  1. Singleton设计由静态式的存在 - 变量会活的范围你懒惰地初始化之后的程序。
  2. 允许全局访问会将您的代码移动到意大利面条逻辑。你最好动态地分配一个你需要的,并将指针传递给你需要的地方。 shared_ptr对此很有帮助。

在这种情况下,您应该找到一种解决单例风格实现的方法,即使它对您更有用 - 它几乎肯定会是更好的设计。

+0

你确定你可以有这样一个托管类的实例并通过引用返回它吗?问题是关于C++/CLI,而不是C++。 – Krizz 2012-02-15 21:47:20

+0

我没有诚实的想法 - 我不知道托管C++,特别是正如我在中间说的。如果你不能,你仍然可以返回一个指向它的指针,至少使它非常类似(我假设)。 – 2012-02-15 21:49:14

+1

我不认为你可以返回指针。我想管理类的唯一选择是管理参考(用'Type ^'表示) – Krizz 2012-02-15 21:51:35