命名空间 + 函数与类上的静态方法

2024-04-24

假设我已经或将要编写一组相关函数。假设它们与数学相关。从组织上来说,我应该:

  1. 编写这些函数并将它们放入我的MyMath命名空间并通过引用它们MyMath::XYZ()
  2. 创建一个名为MyMath并使这些方法静态并引用类似的MyMath::XYZ()

为什么我会选择其中一种作为组织软件的方式?


默认情况下,使用命名空间函数。

类是用来构建对象的,而不是用来替换命名空间的。

在面向对象的代码中

Scott Meyers 在他的《Effective C++》一书中就这个主题写了一个完整的条目,“优先选择非成员非友元函数而不是成员函数”。我在 Herb Sutter 的一篇文章中找到了对这一原则的在线参考:http://www.gotw.ca/gotw/084.htm http://www.gotw.ca/gotw/084.htm

重要的是要知道:在 C++ 中,与类位于同一命名空间中并且以该类作为参数的函数属于该类的接口(因为ADL http://en.wikipedia.org/wiki/Argument_dependent_name_lookup将在解析函数调用时搜索这些函数)。

例如:

  • 假设你有一个命名空间N
  • 假设你有课C,在命名空间中声明N (换句话说,它的全名是N::C)
  • 假设你有一个函数F,在命名空间中声明N (换句话说,它的全名是N::F)
  • 假设这个函数F在其参数中,有一个类型的参数C

... 然后N::F是其一部分N::C的公共接口。

命名空间函数,除非声明为“friend”,否则无法访问类的内部结构,而静态方法有权访问类的内部结构。

这意味着,例如,在维护类时,如果需要更改类的内部结构,则需要在其所有方法(包括静态方法)中搜索副作用。

扩展一

将代码添加到类的接口。

在 C# 中,即使您无权访问类,也可以向类添加方法。但在C++中,这是不可能的。

但是,在 C++ 中,您仍然可以添加命名空间函数,甚至可以添加到某人为您编写的类中。

从另一方面来看,这在设计代码时很重要,因为通过将函数放在命名空间中,您将授权用户增加/完成类的接口。

扩展二

上一点的副作用是,不可能在多个标头中声明静态方法。每个方法都必须在同一个类中声明。

对于命名空间,可以在多个标头中声明来自同一命名空间的函数(几乎标准的交换函数就是最好的例子)。

扩展三

命名空间的基本优点是,在某些代码中,如果使用关键字,则可以避免提及它using:

#include <string>
#include <vector>

// Etc.
{
   using namespace std ;
   // Now, everything from std is accessible without qualification
   string s ; // Ok
   vector v ; // Ok
}

string ss ; // COMPILATION ERROR
vector vv ; // COMPILATION ERROR

您甚至可以将“污染”限制为一类:

#include <string>
#include <vector>

{
   using std::string ;
   string s ; // Ok
   vector v ; // COMPILATION ERROR
}

string ss ; // COMPILATION ERROR
vector vv ; // COMPILATION ERROR

为了正确使用几乎标准的交换习惯用法,此“模式”是必需的。

这对于类中的静态方法来说是不可能做到的。

因此,C++ 命名空间有自己的语义。

但它更进一步,因为您可以以类似于继承的方式组合名称空间。

例如,如果您有一个命名空间A有一个函数AAA,一个命名空间B有一个函数BBB,你可以声明一个命名空间C,并带来AAA and BBB在此名称空间中使用关键字using.

您甚至可以将命名空间的完整内容放入另一个命名空间中,使用using namespace,如命名空间 D! 所示

namespace A
{
   void AAA();
   void AAA2();
}

namespace B
{
   void BBB();
}

namespace C
{
   using A::AAA;
   using B::BBB;
}

namespace D
{
   using namespace A;
   using namespace B;
}

void foo()
{
   C::AAA();
   // C::AAA2(); // ERROR, won't compile
   C::BBB();
}

void bar()
{
   D::AAA();
   D::AAA2();
   D::BBB();
}

结论

命名空间是为了命名空间而存在的。 上课是为了上课。

C++ 的设计使得每个概念都是不同的,并且在不同的情况下以不同的方式使用,作为不同问题的解决方案。

当需要命名空间时不要使用类。

就您而言,您需要命名空间。

本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

命名空间 + 函数与类上的静态方法 的相关文章

  • IIS应用程序池回收+quartz调度

    我正在 IIS 7 5 上运行一个 Web 应用程序 它需要偶尔回收 否则内存使用情况会失控 这是我正在研究的问题 当它回收时 它实际上不会运行 直到另一个请求到来 而quartz不会运行 有没有办法让IIS在回收应用程序池后立即自动启动1
  • 使用 CLion 进行 OpenCV Windows 设置

    我想在 Windows 上为 CLion IDE 设置 OpenCV 我尝试使用 OpenCV 3 1 和 2 4 得到相同的结果 我有 Windows 10 64 位 CLion 使用 cygwin 环境 到目前为止我做了什么 1 从Op
  • json.net自定义jobject反序列化

    我正在尝试使用 JsonConvert DeserializeObject string 将字符串反序列化为可与动态一起使用的 jobject 来动态访问 json 文档 但是我想避免知道文档的大小写 以便我可以输入 dynamic doc
  • 单元测试验证失败

    我正在运行我的单元测试PostMyModel路线 然而 在PostMyModel 我用的是线Validate
  • 在开关中使用“goto”?

    我看到了一个建议的编码标准 内容如下Never use goto unless in a switch statement fall through 我不跟 这个 例外 案例到底是什么样的 这证明了goto 此构造在 C 中是非法的 swi
  • Gwan C#,如何获取HTTP标头?

    我需要它来重写 url 以了解我正在处理哪个友好的 url 用于用户代理和其他东西 EDIT public class Gwan MethodImplAttribute MethodImplOptions InternalCall exte
  • 如何制作可启动程序?

    所以 这个问题可能看起来很奇怪 但假设我编译了 int main void int x 3 int y 4 int z x y 是否可以让CPU这样运行 如何 例如 这允许我写入监视器吗 如果我没记错的话 内存中有些地方可以写入要显示的内容
  • 一元 +/- 运算符如何可能导致“-a”或“+a”中的整数提升,“a”是算术数据类型常量/变量?

    这句看似微不足道的台词摘自我的迈克 巴纳汉和布雷迪的 C 书 第 2 8 8 2 节 http publications gbdirect co uk c book chapter2 expressions and arithmetic h
  • 使用查询表达式对 List 进行排序

    我在使用 Linq 订购这样的结构时遇到问题 public class Person public int ID get set public List
  • 根据对象变量搜索对象列表

    我有一个对象列表 这些对象具有三个变量 ID 名称和值 这个列表中可能有很多对象 我需要根据ID或Name找到一个对象 并更改值 例子 class objec public string Name public int UID public
  • UI 函数在快速事件完成之前触发

    我有一个停靠在 Silverlight 应用程序中的 Web 浏览器框架 有时会在其上弹出全窗口 XAML Silverlight UI 元素 我已经或多或少修复了一个老问题 即 Web 框架的内容似乎与 Silverlight 内容不能很
  • 如何对 NServiceBus.Configure.WithWeb() 进行单元测试?

    我正在构建一个 WCF 服务 该服务接收外部 IP 上的请求并将其转换为通过 NServiceBus 发送的消息 我的单元测试之一调用Global Application Start 它执行应用程序的配置 然后尝试将 Web 服务解析为 验
  • 析构函数中的异步操作

    尝试在类析构函数中运行异步操作失败 这是代码 public class Executor public static void Main var c1 new Class1 c1 DoSomething public class Class
  • 在 asp.net MVC 中使用活动目录进行身份验证

    我想使用活动目录对我的 asp net mvc 项目中的用户进行身份验证 在网上冲浪了几个小时后 我没有找到任何对我有用的东西 我已经看到了所有结果 但什么也没有 我尝试按照许多帖子的建议编辑我的 web config 如果有人可以帮助我提
  • 搜索实体的所有字段

    我正在尝试在客户数据库上实现 多功能框 类型的搜索 其中单个查询应尝试匹配客户的任何属性 这是一些示例数据来说明我想要实现的目标 FirstName LastName PhoneNumber ZipCode Mary Jane 12345
  • 使用具有抗锯齿功能的 C# 更改抗锯齿图像的背景颜色

    我有一个图像需要更改背景颜色 例如 将下面示例图像的背景更改为蓝色 然而 图像是抗锯齿的 所以我不能简单地用不同的颜色替换背景颜色 我尝试过的一种方法是创建第二个图像 仅作为背景 并更改其颜色并将两个图像合并为一个图像 但是这不起作用 因为
  • 使用 GCC 生成可读的程序集?

    我想知道如何使用GCC http en wikipedia org wiki GNU Compiler Collection在我的 C 源文件中转储机器代码的助记符版本 这样我就可以看到我的代码被编译成什么 你可以使用 Java 来做到这一
  • Linux mremap 不释放旧映射?

    我需要一种方法将页面从一个虚拟地址范围复制到另一个虚拟地址范围 而无需实际复制数据 范围很大 延迟很重要 mremap 可以做到这一点 但问题是它也会删除旧的映射 由于我需要在多线程环境中执行此操作 因此我需要旧映射能够同时使用 因此稍后当
  • CUDA 8 编译错误 -std=gnu++11

    我正在尝试转换一些代码以使用 CUDA 并且我认为我遇到了兼容性问题 我们使用CMake 这些是我使用的 gcc 和 CUDA 版本 gcc version gcc Ubuntu 5 4 0 6ubuntu1 16 04 5 5 4 0 2
  • 为什么以下 C 程序会出现总线错误?

    我认为这是第一个失败的 strtok 调用 好久没写C了 有点不知所措 非常感谢 include

随机推荐