2

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?

7
  • Did you try giving it an appropriate default constructor? Although it might be better not to; it's harder to use the class incorrectly if you don't allow default construction. Commented Apr 29, 2015 at 15:24
  • I want to disable possibility of creation object without Create method. Commented Apr 29, 2015 at 15:26
  • 6
    You've already done that. But your question says otherwise: it says you want to be able to default-construct it. You can't both allow and forbid that. Commented Apr 29, 2015 at 15:27
  • Ok. Can I leave a memory to create object afterwards? Commented Apr 29, 2015 at 15:33
  • @HariSeldon I'm not sure what problem you are really about to solve, but I wrote an answer, that will enable you to "create object afterwards". Commented Apr 29, 2015 at 16:01

2 Answers 2

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
}
Sign up to request clarification or add additional context in comments.

6 Comments

friend std::make_unique<SpecialReader>(TCHAR* fileName); error C2063: 'std::make_unique' not a function
Did you include the memory header and is your compiler capable of c++14 standard features? Instead of using std::make_unique() you could also use return std::unique_ptr<SpecialReader>(new SpecialReader(inputFile));.
Yes, I'm include memory header. Second variant work fine (return std::unique_ptr...). But how to delete created object?
@HariSeldon "But how to delete created object?" Did you already read the std::unique_ptr reference? It's actually purposed to take you out of charge of doing this. The delete will be applied as soon the unique_ptr instance used goes out of scope, and it owns a object instance. Ownership for the unique_ptr is transferred to the calling function on return.
But what if I need to recreate whole reader from scratch in some cases?
|
0

Why not have a do-nothing default constructor?

public:
  SpecialReader(){};

1 Comment

If you read the question, you'll recognize the OP doesn't want that (for whatever reasons they have). Only the factory function should be able to create new instances of SpecialReader.

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.