Warning: file_get_contents(/data/phpspider/zhask/data//catemap/0/windows/17.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
C++ C++;拉伊问题_C++_Windows_Raii - Fatal编程技术网

C++ C++;拉伊问题

C++ C++;拉伊问题,c++,windows,raii,C++,Windows,Raii,因此,据我所知,要正确实现RAII,如果我在何处调用CreateFont,我会将其包装在一个类中,在构造函数中使用CreateFont,在析构函数中使用DeleteObject,这样当它超出范围时,它会将其清除 第一个问题是,我会不会有很多班级都这样做?特别是因为类只有构造函数和析构函数 第二个问题是,如果我在WndProc中调用CreateFont类,它会不断超出范围。那么我应该在WndMain中调用CreateFont或类似的LoadBitmap? 我习惯于在WM\u CREATE中调用这些

因此,据我所知,要正确实现RAII,如果我在何处调用
CreateFont
,我会将其包装在一个类中,在构造函数中使用
CreateFont
,在析构函数中使用
DeleteObject
,这样当它超出范围时,它会将其清除

第一个问题是,我会不会有很多班级都这样做?特别是因为类只有构造函数和析构函数

第二个问题是,如果我在WndProc中调用CreateFont类,它会不断超出范围。那么我应该在WndMain中调用
CreateFont
或类似的
LoadBitmap

我习惯于在
WM\u CREATE
中调用这些函数,并在
WM\u DESTROY
中清理它们,通过使用模板帮助您可以避免大量重复工作。例如,如果使用
boost::shared_ptr
可以执行以下操作:

#include <boost/shared_ptr.hpp>
#include <functional>

struct Font;

Font *createFont();
void deleteFont(Font*);

int main() {    
  boost::shared_ptr<Font> font(createFont(), std::ptr_fun(deleteFont));
}
#包括
#包括
结构字体;
Font*createFont();
作废删除字体(字体*);
int main(){
boost::shared_ptr font(createFont(),std::ptr_fun(deleteFont));
}
这样可以节省编写自定义类来管理资源的时间。如果您无法使用boost和TR1或更新版本,您仍然可以自己实现类似的通用工具来提供帮助

boost::shared_ptr
的引用计数正确,因此,如果您想在某个地方创建它并“提升”它以使它更长寿,您可以通过在它死之前将它复制到长寿的地方来实现

第一个问题是,我会不会有很多班级都这样做?特别是因为类只有构造函数和解构器

如果您不喜欢为每种不同类型的对象创建的类的数量,可以创建一个RAII类,该类在构造函数中接受HGDIOBJ参数,并在析构函数中调用DeleteObject。这个类可以用于所有不同的GDI对象。例如:

class GDIObject
{
public:
    HGDIOBJ GdiObject;

    GDIObject( HGDIOBJ object )
        : GdiObject( object )
    {
    }

    ~GDIObject()
    {
        DeleteObject( GdiObject );
    }
}

...

GDIObject font( CreateFont( 48, 0, 0, 0, FW_DONTCARE, false, true, false, DEFAULT_CHARSET, OUT_OUTLINE_PRECIS, CLIP_DEFAULT_PRECIS, CLEARTYPE_QUALITY, VARIABLE_PITCH, TEXT("Impact") ) );
第二个问题是,如果我在WndProc中调用CreateFont类,它会不断超出范围。那么我应该在WndMain中调用CreateFont或类似LoadBitmap吗?我习惯于在WM_CREATE中调用这些函数,并在WM_DESTROY中清理它们


对于需要在内存中保留超过函数作用域时间的项,您必须将它们放在全局级别。

如果您要使用solid RAII,有一些选项可以减少您需要的类的数量-例如,一些boost智能指针(特别是共享的ptr)允许您提供自己的函数,以便在指针超出范围时调用

否则,是的-您将拥有一个用于任何需要显式释放的资源的类-尽管这在代码方面是一个难题,但从长远来看,它将为您节省大量调试时间(尤其是在组项目中)。不过,我还是想说,根据您自己对情况的感受使用RAII——在任何地方使用它都是一个好主意,但有时在转换旧代码时,修复所有调用链以使用它可能需要大量的工作

还有一件事——我对您使用的GUI逻辑不太熟悉,所以我不会专门去那里。。。但是,您必须研究如何复制资源,以及应将其保留多长时间。您的RAII容器是引用计数还是具有值(复制)语义?引用计数智能指针(如shared_ptr)可以解决您经常重新创建资源的问题,只要您可以在代码周围传递对原始资源的引用

第一个问题是,我会不会有很多班级都这样做?特别是因为类只有构造函数和析构函数

是的,但有几点需要考虑:

  • 这是个问题吗?课程规模小,易于阅读和理解
  • 您可能能够重用其中的许多对象(例如,有许多Win32函数创建
    HANDLE
    对象,并且它们都以相同的方式关闭(使用
    CloseHandle
    ),因此您可以为这些对象重用同一类
  • 您可以使用智能指针或其他一些通用包装器来填充大多数样板代码。最流行的智能指针类允许您指定自定义删除器函数
第二个问题是,如果我在WndProc中调用CreateFont类,它会不断超出范围

将其存储在不会过早超出范围的位置。:) 在这里,智能指针可能再次有用。例如,
shared_ptr
可以用来保持字体的活动状态,只要至少有一个
shared_ptr
指向它。然后,您可以简单地将其从函数传递到一些常见的长寿命位置


否则,只要您为RAII类实现复制构造函数和赋值运算符(在C++11中,您可能希望实现移动构造函数和移动赋值),它就可以安全地复制(或移动)到您想要放置它的任何位置,即使它是在较小的范围内创建的。

还有比将RAII对象置于全局级别更好的选项。我想到的一点是:不要将RAII用于范围结束时不会发布的资源。使用RAII的全部目的是为了自动处理资源。如果全局项未使用RAII处理,则应用程序必须手动释放这些项。但是管理资源的全局对象很简单。无论如何,清理这些全局对象需要一些手工工作。是的,最终会有很多类。这就是所有Win32 API包装库最终拥有的功能。也有一个很好的理由,这与RAII无关。Win32 API,特别是GDI部分,有很多概念需要包装!不管你是否使用RAII,你都会得到
窗口
设备
画师
字体
位图
。。。上课。