简体   繁体   中英

How should I handle Inconsistent Objects in C++?

Say, I want to create a File class

class File{
    public:
          File(const char *file){
               openFile(file);
          }
          ~File();
          isEmpty();
};

openFile checks if the file exists or if the contents of the file are valid or not.

File *file = new File("filepath");
if(file)
file->isEmpty();

if my filepath is correct, then all fine, file instance is proper and we can invoke file->isEmpty(); What is the file does not exist, in that case still the check if(file) evaluates to true and will lead to creation of file instance which is actually invalid. How can i guarantee that if file path is invalid, the file instance should be null.

Your constructor should throw an exception in the case that the file couldn't be opened.

File::File( const char* pPath )
{
  if ( !openFile( pPath ) )
    throw FileNotFound( pPath );
}

The only way to do checking like that in the constructor is to throw an exception. But that's not considered good design - you should create it, check if it's valid, and delete it if it isn't.

I suggest using a static factory method that does the check for you and if the object is invalid deletes it and throws an exception. You would create the file like this:

File* file = File::open("whatever");

If I understand what you correctly, you want to return null from the constructor when "filepath" is invalid? This isn't (directly) possible in C++, although there are a few possibilities. You could throw an exception from your constructor, but this can get hairy in C++. You could have some functions that can check the validity of a File object, so if(file) would become if(isValid(file)) . You could also wrap some of this logic in some sort of factory that would return null if the file to be created is invalid.

I would use the STL, templates and throw an empty class. Now, you can't return anything from a constructor... so either do something like this:

#include <string>
using std::basic_string;

class EmptyFile{};

template<typename T>
    class File
    {
    public:
        File(const basic_string<T> &FILE)
        {
            if (isEmpty(FILE)) throw EmptyFile();
            openFile(FILE);
        }
        bool isEmpty(const basic_string<T> &FILE) const
            { return FILE.empty(); }
    };

or you could do this:

#include <string>
using std::basic_string;

template<typename T>
class File
{
public:
    bool Open(const basic_string<T> &FILE) const
    {
        bool empty = isEmpty(FILE);
        if(!empty)
           /* open the file */;
        return isEmpty;
    }
    bool isEmpty(const basic_string<T> &FILE) const
    { return FILE.empty(); }
};

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM