Ошибка «Инициализатор не называет элемент данных или базовый класс, не находящийся в состоянии c», когда инициализатор является именем базового класса - PullRequest
0 голосов
/ 15 января 2020

Я столкнулся со следующей проблемой. В файле my_exception.h я определил свой собственный класс исключений, унаследованный от std::exception:

// File "my_exception.h"
#include <exception>
#include <string>

namespace proj { namespace exception {

struct Exception : public std::exception {
    explicit Exception(const std::string& msg) noexcept : msg_(msg) { }

    inline const char* what() const noexcept override { return msg_.c_str(); }

private:
    std::string msg_;
};

} }

Затем я определил производный класс исключений с именем BadParameterAccess в другом пространстве имен, разделив его объявление и реализация в файлах .h и . cpp соответственно:

// File parameter_exception.h
#include "exception.h"

namespace proj { namespace parameter {

struct BadParameterAccess final : public exception::Exception
{
    BadParameterAccess() noexcept;
};

} }

// File parameter_exception.cpp
#include "parameter_exception.h"

namespace proj { namespace parameter {

BadParameterAccess::BadParameterAccess() noexcept
    : exception::Exception("[BadParameterAccess] parameter not set yet."){ }

} }

Я попытался скомпилировать этот код, используя несколько компиляторов. С clang 6.0 я получаю следующую ошибку:

parameter_exception.cpp:7:18: error: initializer 'Exception' does not name a non-static data member or base class; did you mean the base class 'Exception'?
    : exception::Exception("[BadParameterAccess] parameter not set yet."){ }
                 ^~~~~~~~~
                 Exception
./parameter_exception.h:11:35: note: base class 'exception::Exception' specified here
struct BadParameterAccess final : public exception::Exception
                                  ^~~~~~~~~~~~~~~~~~~~~~~~~~~

g ++ 7 выдает эквивалентную ошибку, а Visual Studio 2017 дает следующее:

parameter_exception.cpp(8): error C2039: 'Exception': is not a member of 'std::exception'

Код прекрасно компилируется, когда либо:

  1. в файле parameter_exception. cpp Я указываю полный путь для инициализатора базового класса (proj::exception::Exception) или
  2. в файле parameter_exception. cpp Я удаляю пространства имен из инициализатора базового класса (Exception) или
  3. в файле my_exception.h Удаляю наследование от std::exception или
  4. Я переименую свое пространство имен exception другим способом.

Насколько я понял из разных ошибок, которые я получил, компилятор ожидает найти элемент вызывается Exception внутри класса std::exception, а не внутри пространства имен exception, но я не понимаю, почему это происходит. Более того, я ожидал, что компилятор выдаст мне ошибку, когда я сначала унаследую от exception::Exception в заголовочном файле parameter_exception.h , но это не так.

Может кто-нибудь объяснить мне причина?

Заранее спасибо.

1 Ответ

1 голос
/ 15 января 2020

как подсказывает @molbdnilo, существует проблема поиска имени. проблема в том, что имя «исключение» используется для исключения пространства имен и стандартная структура :: исключение. Я удалил код и комментарии из кода, который вы опубликовали.

namespace standard {
    struct exception{
        explicit exception() noexcept { }
    };
}
namespace exception {
    struct A: public standard::exception {
        explicit A() noexcept { }
    };
}
namespace parameter {
    struct BadParameterAccess final : public exception::A
    {
        //BadParameterAccess() noexcept : exception::A() { }; // KO
        BadParameterAccess() noexcept : ::exception::A() { }; // OK
    };
}

namespace standard1 {
    struct exception1{
        explicit exception1() noexcept { }
    };
}
namespace exception2 {
    struct A: public standard1::exception1 {
        explicit A() noexcept { }
    };
}
namespace parameter1 {
    struct BadParameterAccess1 final : public exception2::A
    {
        BadParameterAccess1() noexcept : exception2::A() { }; // OK
        //BadParameterAccess1() noexcept : ::exception2::A() { }; // OK
    };
}
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...