我正在尽力解释这种情况。我希望,我写的,是可以理解的。 我们已经定义了类
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和内存泄漏问题。 这是我的示例代码, 从测试类派生的特殊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;
}
我测试了上面的模式,它起作用了。
谢谢你们,
L.E。
答案 0 :(得分:2)
这是一个好方法吗?
我可能不会认为这是一个好的方法,因为你将一个单独的类作为单例和普通类,你可以直接实例。
通常情况下,如果您需要单身,这将排除能够实例化该类的需要或愿望。
如果你真的需要一种方法来拥有这个类的“全局”实例,我会将它封装在一个实现单例的单独类中。至少,这将清楚表明您正在处理在这种情况下是单个实例的事情。我不会将两个用例混合到一个类中。
答案 1 :(得分:1)
我不确定你可能会遇到什么情况需要单一样式的语义和同一类的普通创建语义。
就你编码的内容而言,它看起来完全没问题。我唯一的评论是,Instance()
函数不需要在Car
上执行构造,Instance()
函数应该只调用TestClass
的默认构造函数,它应该执行所有操作这一点。
修改强>
参考:
@crush。该类已经定义我只需要获取它的静态对象。 Singleton只表示该类的一个对象,但在这种情况下,类具有多个普通对象。但我想只在有限的时间段内使用此类的一个对象来实现一个特定的目标。 - L.E. 2分钟前
单身人士(通常)是糟糕设计的标志 - 很多人实际上称之为反模式。如果你只是需要这个类的一个特定实例,在有限的时间内存在一些问题:
在这种情况下你应该找到解决单例式实现的方法,即使它对你来说更有用 - 它几乎肯定会是更好的设计。
答案 2 :(得分:1)
嗯,实际上代码中存在内存泄漏问题。
您只声明virtual ~TestClass();
,对于托管类,C ++ / CLI编译器在内部将其转换为IDisposable.Dispose()
的实现。
因此,如果您将delete car
放入其中,则只有在您delete test_class
或者using (TestClass tst) {}
时才会调用它。从C#开始使用时会进入!MyClass();
块。
当对象被GC时,不会被调用!
为了确保它被调用,你需要为你的类virtual void Finalize()
添加终结器,它由编译器转换为m_car
,因此当GC释放一个对象时会被非确定性地调用。
这是释放单身对象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}}