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

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(使用前将#替换为@)

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

  • 如何在 DataColumn.Expression 中使用 IF/ELSE 或 CASE?

    我有一个包含 1 列的表 状态 我想添加另一列名为 Action 的列 其值如下 如果 Status Yes 则 Action Go 否则 Action Stop 我使用以下代码添加到 操作 列中 但它不起作用 myDataTable Co
  • 在 C# 中按元素相乘数组具有意想不到的性能

    我想找到按元素相乘两个数组的最佳方法 这是更广泛项目的一部分 其中性能而不是唯一的考虑因素 我今天开始用 C Linqpad 编写一些函数 因此它还没有以任何方式进行优化 下面代码的输出如下 Environment ProcessorCou
  • 何时使用 =default 使析构函数默认?

    尽管对构造函数使用 default 对我来说很清楚 即强制编译器在其他构造函数存在时创建默认构造函数 但我仍然无法理解这两种类型的析构函数之间的区别 那些使用 default 的 那些没有显式定义并由编译器自动生成的 我唯一想到的是 gro
  • 更改 Qt OpenGL 窗口示例以使用 OpenGL 3.3

    我正在尝试更改 Qt OpenGL 示例以使用更现代的 opengl 版本 330 似乎合适 所以我做了 在 main cpp 上设置版本和配置文件 设置着色器版本 更改着色器以使用统一 它现在构建没有任何错误 但我只看到一个空白窗口 我错
  • 平滑滚动.net 表单

    您好 我正在 net 中使用表单 并且在运行时动态添加大量链接标签 我将这些链接标签添加到面板并将该面板添加到 winform 当链接标签的数量增加时 表单会显示一个自动滚动条 垂直 现在 当我使用自动滚动向下滚动时 表单在滚动时不会更新其
  • VS 程序在调试模式下崩溃,但在发布模式下不崩溃?

    我正在 VS 2012 中运行以下程序来尝试 Thrust 函数查找 include cuda runtime h include device launch parameters h include
  • 读取 C# 中的默认应用程序设置

    我的自定义网格控件有许多应用程序设置 在用户范围内 其中大部分是颜色设置 我有一个表单 用户可以在其中自定义这些颜色 并且我想添加一个用于恢复默认颜色设置的按钮 如何读取默认设置 例如 我有一个名为的用户设置CellBackgroundCo
  • 信号处理程序有单独的堆栈吗?

    信号处理程序是否有单独的堆栈 就像每个线程都有单独的堆栈一样 这是在 Linux C 环境中 来自 Linux 手册页signal 7 http kernel org doc man pages online pages man7 sign
  • 指向特征矩阵的指针数组

    我在代码中使用 Eigen 的 MatrixXd 矩阵 在某个时刻我需要一个 3D 矩阵 由于 Eigen 没有三维矩阵类型 因为它仅针对线性代数进行了优化 因此我创建了一个 MatrixXd 类型的指针数组 Eigen MatrixXd
  • 单例模式和 std::unique_ptr

    std unique ptr唯一地控制它指向的对象 因此不使用引用计数 单例确保利用引用计数只能创建一个对象 那么会std unique ptr与单例执行相同 单例确保只有一个实例属于一种类型 A unique ptr确保只有一个智能指针到
  • Visual Studio Code:如何配置 includePath 以获得更好的 IntelliSense 结果

    我是使用 Visual Studio Code 的完全初学者 我不知道我在做什么 我已经四处搜索 也许还不够 但我找不到像我这样的人如何配置的简单解释c cpp properties json每当我单击带有绿色波浪线下划线的行旁边的黄色灯泡
  • 如何从文本文件读取整数到数组

    这就是我想做的 我对此有些不满 但我希望你能容忍我 这对我来说是一个非常新的概念 1 在我的程序中 我希望创建一个包含 50 个整数的数组来保存来自文件的数据 我的程序必须获取用户的文档文件夹的路径 2 文件的名称为 grades txt
  • C++ php 和静态库

    我创建了一个library a 其中包含 cpp 和 h 文件 其中包含很多类 嵌套类和方法 我想在 php 示例中包含这个静态库并尝试使用它 我想提一下 我是 php 新手 我已经在 test cpp 文件中测试了我的 libray a
  • 无法在内存位置找到异常源:cudaError_enum

    我正在尝试确定 Microsoft C 异常的来源 test fft exe 中 0x770ab9bc 处的第一次机会异常 Microsoft C 异常 内存位置 0x016cf234 处的 cudaError enum 我的构建环境是 I
  • .NET Core 中的跨平台文件名处理

    如何处理文件名System IO以跨平台方式运行类以使其在 Windows 和 Linux 上运行 例如 我编写的代码在 Windows 上完美运行 但它不会在 Ubuntu Linux 上创建文件 var tempFilename Dat
  • 您是否将信息添加到每个 .hpp/.cpp 文件的顶部? [关闭]

    Closed 这个问题是基于意见的 help closed questions 目前不接受答案 创建新的 C 头文件 源文件时 您会在顶部添加哪些信息 例如 您是否添加日期 您的姓名 文件描述等 您是否使用结构化格式来存储此信息 e g F
  • 矩阵到数组 C#

    这将是转换方阵的最有效方法 例如 1 2 3 4 5 6 7 8 9 into 1 2 3 4 5 6 7 8 9 in c 我在做 int array2D new int 1 2 3 4 5 6 7 8 9 int array1D new
  • 将 char[][] 转换为 char** 会导致段错误吗?

    好吧 我的 C 有点生疏了 但我想我应该用 C 来做我的下一个 小 项目 这样我就可以对其进行抛光 并且我已经有不到 20 行的段错误了 这是我的完整代码 define ROWS 4 define COLS 4 char main map
  • C++0x中disable_if在哪里?

    Boost 两者都有enable if and disable if 但 C 0x 似乎缺少后者 为什么它被排除在外 C 0x 中是否有元编程工具允许我构建disable if按照enable if 哦 我刚刚注意到std enable i
  • 从 JavaScript 中的 OnClientClick 事件中阻止 C# 中的 asp:Button OnClick 事件?

    我有一个asp Button在我的网页上 它调用 JavaScript 函数和代码隐藏方法 后者进行调用以导航到另一个页面 在 JavaScript 函数中 我正在检查条件 如果不满足这个条件 我想中止导航 以便OnClick方法未被调用

随机推荐