Создайте объект, вызвав конструктор (метод) явно - PullRequest
2 голосов
/ 27 сентября 2011

Определение класса:

#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

У меня есть кусок кода в файле 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;
}

И в другом файле fs_creation.cpp:

int FSCreation::GenerateFS() {
int result;
try {
    result = ImprDoMakeTree(); //This call pos_close 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;
}

На моей версии компилятора эта компилируется и работает правильно:
g ++ (Ubuntu / Linaro 4.4.4-14ubuntu5) 4.4.5 (Ubuntu Maverick - 10.04)
В другой версии компилятора:
g ++ (Ubuntu / Linaro 4.5.2-8ubuntu4) 4.5.2 (Ubuntu Narwhal - 11.04) вызывает
Ошибка:
posix_lib.cpp: в функции int pos_close (int):
posix_lib.cpp: 363: 46: ошибка: невозможно вызвать конструктор ‘print_errors :: Error :: Error ’напрямую
posix_lib.cpp: 363: 46: ошибка: для приведения в стиле функции удалите лишнюю ‘:: Error’
Вопросы:
1. Почему это работает на одной версии g ++ и не работает на другой?
2. Что происходит, когда я явно вызываю конструктор для создания объекта? Это правильно?
И почему это работает?

Ответы [ 5 ]

5 голосов
/ 27 сентября 2011

Вы не вызываете конструктор (ну, вы, но не так, как вы это имеете в виду) Синтаксис ClassName(constructor params) означает создание временного объекта типа ClassName, используя заданные параметры для его конструктора. Таким образом, вы не просто вызываете конструктор; вы создаете объект.

Итак, вы создаете Error объект. Ваша проблема в том, что имя Error - impress_errors::Error, а не «strike_errors :: Error :: Error». Второй ::Error может показаться попыткой назвать конструктор. Конструкторы не имеют имен; они не являются функциями, которые вы можете найти и вызвать по своей прихоти (опять же, не так, как вы этого хотите).

1 голос
/ 27 сентября 2011

Это похоже на ошибку в компиляторе, который отклоняет его.Кодекс допустим, но не по тем причинам, о которых вы думаете.Нет такой вещи как «явный вызов конструктора (метода)», потому что у конструкторов нет имен (§12.1 / 1).С другой стороны, impress_errors::Error::Error - это имя типа;внедрение имени класса (§9 / 2) означает, что класс impress_errors::Error содержит объявление имени Error в классе в качестве синонима имени вне класса.Таким образом, impress_errors::Error, impress_errors::Error::Error, impress_errors::Error::Error::Error и т. Д. Все называют одним и тем же типом (хотя только первый является идиоматическим - все остальные - просто дополнительный шум).И когда за именем типа следует список выражений в скобках, как в данном случае, это «Преобразование типа Explicity (функциональная запись)».(§5.2.3 - и стандарт говорит, что это явное преобразование типов, даже если список выражений пуст или содержит более одного выражения - не спрашивайте меня, какой «тип» преобразуется в таких случаях.) Итак impress_errors::Error(err_code) (или impress_errors::Error::Error(err_code) означает преобразование err_code в impress_errors::Error. Что, в данном случае, приведет к вызову конструктора, поскольку это единственный способ преобразовать int в impress_errors::Error. (Этооднако можно построить случаи, когда компилятор будет вызывать пользовательскую функцию преобразования для преобразуемого объекта.)

0 голосов
/ 17 марта 2016

Я столкнулся с точно таким же сообщением об ошибке.

Решение состоит в том, чтобы изменить эту строку:

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

до

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

В C ++ вы можете вызывать конструктор базового класса внутри конструктора производного класса, просто никогда не используйте оператор разрешения контекста ::

0 голосов
/ 27 сентября 2011

Хотя вы можете явно вызывать конструктор с помощью размещения new, см. операторы размещения , у вас еще нет объекта или части памяти, в которую можно поместить объект. Вероятно, проще использовать что-то вроде

выбросить новую ошибку MyError (MyParams);

и возложить на обработчик исключений ответственность за его удаление. FWIW Microsoft использует этот подход с MFC.

0 голосов
/ 27 сентября 2011

Все должно быть в порядке, если вы делаете то, что запрашивает компилятор. Просто удалите один оператор «Error»;> Я не уверен, почему это изменилось в gcc, но class_name :: construction_name просто избыточно. Компилятор знает, что вы хотите вызвать конструктор, потому что его имя совпадает с именем класса

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...