开发者

Construct object by calling constructor (method) explicitly

Definition of class:

#pragma once
#include <string>
#include <utility>

namespace impress_errors {

#define BUFSIZE 512

class Error {
public:
    Error(int number);
    Error(std::string message);
    Error(const char *message);
    bool IsSystemError();
    std::string GetErrorDescription();

private:
    std::pair <int, std::string> error;
    char stringerror[BUFSIZE]; // Buffer for string describing error
    bool syserror;
};

}  // namespace impres_errors

I have some piece of code in file posix_lib.cpp:

int pos_close(int fd)
{
    int ret;
    if ((ret = close(fd)) < 0) {
        char err_msg[4096];
        int err_code = errno;
        throw impress_errors::Error::Error(err_code); //Call constructor explicitly
    }
    return ret;
}

And in another file fs_creation.cpp:

int FSCreation::GenerateFS() {
int result;
try {
    result = ImprDoMakeTree(); //This call pos_close开发者_JS百科 inside.
}
catch (impress_errors::Error error) {
    logger.LogERROR(error.GetErrorDescription());
    return ID_FSCREATE_MAKE_TREE_ERROR;
}
catch (...) {
    logger.LogERROR("Unexpected error in IMPRESSIONS MODULE");
    return ID_FSCREATE_MAKE_TREE_ERROR;
}
if(result == EXIT_FAILURE) {
    return ID_FSCREATE_MAKE_TREE_ERROR;
}
return ID_SUCCESS;
}

On my version of compiler this one is compiled and work correct:

g++ (Ubuntu/Linaro 4.4.4-14ubuntu5) 4.4.5 (Ubuntu Maverick - 10.04)

On another version of compiler:

g++ (Ubuntu/Linaro 4.5.2-8ubuntu4) 4.5.2 (Ubuntu Narwhal - 11.04) it causes

error:

posix_lib.cpp: In function ‘int pos_close(int)’:

posix_lib.cpp:363:46: error: cannot call constructor ‘impress_errors::Error::Error’ directly

posix_lib.cpp:363:46: error: for a function-style cast, remove the redundant ‘::Error’

Questions:

1. Why this work on one version of g++, and failed on another?

2. What happens when I explicitly call constructor for creating object? Is it correct?

And why this is working?


You are not calling the constructor (well, you are, but not in the way you mean it). The syntax ClassName(constructor params) means to create a temporary object of the type ClassName, using the given parameters for its constructor. So you aren't simply calling the constructor; you are creating an object.

So you are creating an Error object. Your problem is that the name of Error is impress_errors::Error, not "impress_errors::Error::Error". The second ::Error would seem to be an attempt to name the constructor. Constructors don't have names; they are not functions that you can find and call at your whim (again, not in the way you mean it).


This looks like an error in the compiler which rejects it. The code is legal, but not for the reasons you think. There is no such thing as "calling constructor (method) explicitly", because constructors don't have names (§12.1/1). On the other hand, impress_errors::Error::Error is the name of a type; class name injection (§9/2) means that the class impress_errors::Error contains a declaration of the name Error in the class, as a synonym for the name outside of the class. So impress_errors::Error, impress_errors::Error::Error, impress_errors::Error::Error::Error, etc. all name the same type (although only the first is idiomatic—the rest are all just extra noise). And when the name of a type is followed by a parenthesized expression list, as is the case here, it is an "Explicity type conversion (functional notation)". (§5.2.3—and the standard says it is an explicit type conversion even if the expression list is empty, or contains more than one expression—don't ask me what "type" is being converted in such cases.) So impress_errors::Error(err_code) (or impress_errors::Error::Error(err_code) means convert err_code into an impress_errors::Error. Which, in this case, will result in calling the constructor, since that's the only way to convert an int into an impress_errors::Error. (It's possible, however, to construct cases where the compiler will call a user defined conversion function on the object being converted.)


It should be ok if You do what compiler is asking You. Just remove one "Error" statement;> I'm not sure why this changed in gcc, but class_name::construction_name is just redundant. Compiler knows that You want to call constructor, because its name is the same as the name of the class


While you could explicitly call the constructor using placement new, see placement operators, you don't have an object or piece of memory in which to place the object yet. Probably easier to use something like

throw new MyError(MyParams);

and make the exception handler responsible for deleting it. FWIW Microsoft use this approach with MFC.


I ran into the exact same error message.

The solution is to change this line:

throw impress_errors::Error::Error(err_code); //Call constructor explicitly

to

throw impress_errors::Error(err_code); //Call constructor explicitly

In C++ you can call the base class constructor inside a derived class constructor, just never use the scope resolution operator ::

0

上一篇:

下一篇:

精彩评论

暂无评论...
验证码 换一张
取 消

最新问答

问答排行榜