C++ FAQ Celebrating Twenty-One Years of the C++ FAQ!!!
(Click here for a personal note from Marshall Cline.)
Section 11:
[11.8] What if I can't wrap the local in an artificial block?

Most of the time, you can limit the lifetime of a local by wrapping the local in an artificial block ({...}). But if for some reason you can't do that, add a member function that has a similar effect as the destructor. But do not call the destructor itself!

For example, in the case of class File, you might add a close() method. Typically the destructor will simply call this close() method. Note that the close() method will need to mark the File object so a subsequent call won't re-close an already-closed File. E.g., it might set the fileHandle_ data member to some nonsensical value such as -1, and it might check at the beginning to see if the fileHandle_ is already equal to -1:

class File {
public:
  void close();
  ~File();
  ...
private:
  int fileHandle_;   // fileHandle_ >= 0 if/only-if it's open
};

File::~File()
{
  close();
}

void File::close()
{
  if (fileHandle_ >= 0) {
    ...code that calls the OS to close the file...
    fileHandle_ = -1;
  }
}
Note that the other File methods may also need to check if the fileHandle_ is -1 (i.e., check if the File is closed).

Note also that any constructors that don't actually open a file should set fileHandle_ to -1.