C++ c++;17名称空间,是否可以强制始终进行限定访问?

C++ c++;17名称空间,是否可以强制始终进行限定访问?,c++,namespaces,C++,Namespaces,令我惊讶的是,当函数与变量在同一名称空间中声明时,该函数可能会无条件地访问该变量 // file qqq.cpp namespace aaa { void f(); int x; } void aaa::f() { aaa::x; // 0. INTENDED ACCESS to x in namespace aaa (also works) x; // 1. SURPRISE: x can be accessed with

令我惊讶的是,当函数与变量在同一名称空间中声明时,该函数可能会无条件地访问该变量

// file qqq.cpp

namespace aaa {
    void f();
    int x; 
}

void aaa::f() {
    aaa::x;       // 0. INTENDED ACCESS to x in namespace aaa (also works)
    x;            // 1. SURPRISE: x can be accessed without aaa:: qualification
    bool x;       // 2. SURPRISE: given (1) why is it allowed to redefine x?
}
问题:

A) 有没有办法确保名称空间中的所有对象都对其其他组成部分视而不见,并要求始终通过以下方式进行访问:

B) 如果不是,那么获得所需行为的正确编码实践是什么

C) 如果不是,另一种解决方案是将每个名称空间分成2个,一个用于函数,另一个用于变量,如f_aaa和v_aaa。但这在实际使用中似乎相当笨拙和丑陋,例如void f_sqlite::myfun(){v_sqlite::myvar;}而不是void sqlite::myfun(){sqlite::myvar;}


编辑1:上下文,我试图解决的“问题”:

通过重构数千行代码,名称空间被认为适合捆绑相关元素,例如用于整个代码库中使用的sqlite实用程序函数和变量的“sqlite”名称空间。通过::强制访问将是一种提高清晰度、避免名称冲突和隐藏的极好方法。为“一个bundle”单独使用名称空间将无法达到此目的。类在概念上似乎不合适

编辑2:

D) 当命名空间aaa中的函数在没有限定条件的情况下访问命名空间aaa中的变量时,是否可能获得警告(启用编译器标志)以发出信号

编辑3:

我想我最终还是会使用“单独的名称空间”,但是使用嵌套的名称空间

// file qqq.cpp

namespace aaa::f { // namespace for functions
    void f();
    void g();
}

namespace aaa::v { // namespace for variables
    int x;
}

// definition of function f inside namespace aaa::f

void aaa::f::f() {
    aaa::v::x;    // only way of accessing x in aaa::v (good) (ugly)
    x;            // compiler error (good)
    bool x;       // normal scope hiding (good)
    g();          // works: ARGH! would like to force qualifying with aaa::f::
}
不过还是挺难看的。还有!函数仍然可以相互调用不合格,对象仍然可以相互调用/引用不合格。如果能够在名称空间中的所有或某些元素上放置一些“强制限定符”(如“private”),那就太好了

A) 有没有办法防止名称空间中的所有对象对其其他组成部分视而不见,并要求始终通过以下方式进行访问:

没有

B) 如果不是,那么获得所需行为的正确编码实践是什么

使用

C) 如果没有,另一种解决方案是将aaa名称空间分为2个,一个用于函数,另一个用于变量,如f_aaa和v_aaa。但这在实际使用中似乎相当笨拙和丑陋,例如void f_sqlite::myfun(){v_sqlite::myvar;}而不是void sqlite::myfun(){sqlite::myvar;}

使用
将相关函数和数据分组在一起。要隐藏的内容放在
private
部分

A) 有没有办法防止名称空间中的所有对象对其其他组成部分视而不见,并要求始终通过以下方式进行访问:

没有

B) 如果不是,那么获得所需行为的正确编码实践是什么

使用

C) 如果没有,另一种解决方案是将aaa名称空间分为2个,一个用于函数,另一个用于变量,如f_aaa和v_aaa。但这在实际使用中似乎相当笨拙和丑陋,例如void f_sqlite::myfun(){v_sqlite::myvar;}而不是void sqlite::myfun(){sqlite::myvar;}

使用
将相关函数和数据分组在一起。要隐藏的内容放在
private
部分

为函数和变量使用单独的(嵌套的)名称空间不是一个好主意。这会降低代码的可读性

此外,总是限定所有名称也太过分了。如果函数
f
位于名称空间
aaa
中,那么它应该更喜欢来自该名称空间的变量

最后,出现这种问题的唯一原因是您使用了太多的全局变量(或长函数),这是一种非常糟糕的做法,因为这会使代码更难维护

因此我建议您使用好的编码实践

  • 小功能(小于一个屏幕)
  • 避免全局变量
  • 适当时使用带有成员函数和数据的类进行面向对象的设计
  • 小文件(这样你就不会得到不相关的东西)
  • 避免头文件中的变量
  • 只包含您真正需要的文件(因此,如果有冲突,您不会遇到太多冲突)
事实上,如果您确实遇到了问题,这是因为当前代码太大,并且没有遵循好的做法。

注释和答案中的其他变通方法可能会起作用,但最好验证您的设计是否充分,并根据需要重构代码

额外积分:

另一件可能导致很多歧义的事情是,当您真正应该使用自定义类型时,使用基本数据类型

  • 当您希望对特定参数使用某个常量而不是定义整数时,使用类型化枚举(
    enum class
  • 如果有捆绑在一起并在整个应用程序中使用的数据,则使用类或结构
  • <> LI>如果使用模板函数,您可能需要仔细考虑它将允许的数据类型,特别是如果您的函数有一个通用的名称,例如“代码>打开/代码>。
      为函数和变量使用单独的(嵌套的)名称空间不是一个好主意。这会降低代码的可读性

      此外,总是限定所有名称也太过分了。如果函数
      f
      位于名称空间
      aaa
      中,那么它应该更喜欢来自该名称空间的变量

      最后,出现这种问题的唯一原因是您使用了太多的全局变量(或长函数),这是一种非常糟糕的做法,因为这会使代码更难维护

      因此我建议您使用好的编码实践

      • 小功能(小于一个屏幕)
      • 避免全局变量
      • 面向对象设计