Oomph Sonar
Oomph Sonar

Reputation: 803

Define factory class in C++

I have "like factory" class:

class SpecialReader {
private:
    HANDLE specialFile;
    SpecialReader(HANDLE specialFile);
public:
    static SpecialReader Create(TCHAR* fileName);
    ~SpecialReader();
}

//where 

SpecialReader::Create(TCHAR* fileName) {
// ...
// ...

return SpecialReader(inputFile);
}

I want to define object in program body like this:

SpecialReader myReader;

But not:

SpecialReader myReader = SpecialReader::Create(anyFile);

If I try to define object like in the first case I've got a compiler error:

error C2512: 'SpecialReader' : no appropriate default constructor available. 

How to define this class right?

Upvotes: 2

Views: 169

Answers (2)

πάντα ῥεῖ
πάντα ῥεῖ

Reputation: 1

You can use a smart pointer to do so, the simplest choice is using a std::unique_ptr<SpecialReader> and transfer ownership of the instance to the caller:

class SpecialReader {
private:
    HANDLE specialFile;
    SpecialReader(HANDLE specialFile);        
public:
    static std::unique_ptr<SpecialReader> Create(TCHAR* fileName);
        // ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
    ~SpecialReader();
}

std::unique_ptr<SpecialReader> SpecialReader::Create(TCHAR* fileName) {
    // ...
    return std::unique_ptr<SpecialReader>(new SpecialReader(inputFile));
}

To get delayed creation you can write as follows. The syntax is slightly different from your OP, but effectively achieves the same:

std::unique_ptr<SpecialReader> myReader;

// ....

myReader = SpecialReader::Create(filename);

As for your comments, that you want to handle failure within the Create() factory function, you can return an empty std::unique_ptr<SpecialReader>, and let the client check about it:

std::unique_ptr<SpecialReader> SpecialReader::Create(TCHAR* fileName) {
    try {
        // ...
        return std::unique_ptr<SpecialReader>(new SpecialReader(inputFile));
    }
    catch(...) {
        // ignore any exceptions
    }
    return std::unique_ptr<SpecialReader>();
}

std::unique_ptr<SpecialReader> myReader;
myReader = SpecialReader::Create(filename);
if(!myReader.get()) {
    // Error handling, Create() couldn't create an instance of SpecialReader
}

Upvotes: 2

Haytham Yaghi
Haytham Yaghi

Reputation: 45

Why not have a do-nothing default constructor?

public:
  SpecialReader(){};

Upvotes: 1

Related Questions