c++ - 当初始化程序是基类名称时,错误“初始化程序没有命名非静态数据成员或基类”
问题描述
我面临以下问题。在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'
代码在以下任一情况下都能完美编译:
- 在文件parameter_exception.cpp中,我指定了基类初始化程序 (
proj::exception::Exception
) 的完整路径,或者 - 在文件parameter_exception.cpp中,我从基类初始化程序 (
Exception
) 中删除命名空间,或者 - 在my_exception.h文件中,我从
std::exception
, 或 exception
我以其他方式重命名我的命名空间。
据我从我得到的不同错误中了解到,编译器希望找到一个Exception
在类std::exception
内部而不是在 namespace 内部调用的成员exception
,但我不明白为什么会发生这种情况。exception::Exception
此外,当我首先从头文件parameter_exception.h中继承时,我希望编译器会给我一个错误,但事实并非如此。
有人可以解释一下原因吗?
先感谢您。
解决方案
正如@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
};
}
推荐阅读
- pandas - 检查一个数据框中一列中的值是否在另一个数据框中两列中的值之间的范围内
- javascript - 如果设置了另一个字段,则验证表单中的字段
- java - Spring Data 返回类型为抽象类或接口错误
- matlab - ZMCSCG频道的代码是这样的吗?h_1=sqrt(1/2)*(randn(N,1)+1i*randn(N,1));
- java - Excel 数据未填充到 Web 表单中
- python - 将多个值分配给数据框中的不同单元格
- mysql - Laravel 5.7 迁移拆分读写数据库的问题
- google-cloud-platform - VPC 原生 GKE 集群生产准备好了吗?
- python - Django python AttributeError异常值:'WSGIRequest'对象没有属性'shop'
- c# - PInvoking AddSecurityPackageA