C++ 使用命名空间来避免长路径

发布于 2024-07-15 18:13:41 字数 835 浏览 9 评论 0原文

我仍在学习 C++,之前从未真正创建过自己的命名空间。 我正在用它们进行实验,虽然我完成了大部分工作,但有一件事我似乎仍然无法做到。 我希望能够在类中调用静态方法,而无需输入类似 NameOfClass::method 的内容。 这是我认为代码应该是这样的,但它无法编译:

文件 Ah

namespace Test
{
    class A
    {
        public:
            static int foo() { return 42; }
    };
}

文件 main.cpp

#include <iostream>

#include "A.h"

using namespace std;
using namespace Test::A;

int main()
{
    cout << foo() << endl;

    return 0;
}

编译器给我:

main.cpp:6: error: ‘A’ is not a namespace-name
main.cpp:6: error: expected namespace-name before ‘;’ token
main.cpp: In function ‘int main()’:
main.cpp:10: error: ‘foo’ was not declared in this scope

是否可以执行什么操作我想在不输入 A::foo 的情况下进行操作?

I am still learning C++, and I have never really created my own namespaces before. I was experimenting with them and while I got most things to work, there's one thing that I still can't seem to do. I would like to be able to call a static method within a class without typing something like NameOfClass::method. Here is what I thought the code should look like, but it fails to compile:

File A.h,

namespace Test
{
    class A
    {
        public:
            static int foo() { return 42; }
    };
}

File main.cpp,

#include <iostream>

#include "A.h"

using namespace std;
using namespace Test::A;

int main()
{
    cout << foo() << endl;

    return 0;
}

The compiler gives me:

main.cpp:6: error: ‘A’ is not a namespace-name
main.cpp:6: error: expected namespace-name before ‘;’ token
main.cpp: In function ‘int main()’:
main.cpp:10: error: ‘foo’ was not declared in this scope

Is it possible to do what I am trying to do without typing A::foo?

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(4

隐诗 2024-07-22 18:13:41

在 C++ 中,您/尤其是/必须仔细阅读编译器错误消息。

请注意,第一个错误是“错误:‘A’不是命名空间名称”。 确实如此,A 是一个类名。

using namespace Foo; // brings in  all of foo;
using Bar::Baz // brings in only Baz from Bar

你想写:

using Test::A;

这有两个好处:它引入 A 供你使用,并且它不会引入 Test 的所有其余部分,这也很好,因为你应该只引入你需要的内容,以便不要意外地依赖于你没有意识到自己正在依赖的东西。

但是,由于 foo 在 A 中是静态的,因此您仍然必须显式引用 A::foo 。 (除非你做了一些事情,比如编写一个转发到 A::foo 的自由函数;一般来说,如果你这样做只是为了节省一些打字,那么这是一个坏主意。)

有些人可能建议根本不使用 using 声明,而是完全限定所有名称。

但这是(引用 Stroustrup 的话)“乏味且容易出错”,并且它妨碍了重构:假设您完全限定了 FooMatic::Stack 类的每次使用,然后管理层坚持要求,就在您准备这样做之前进入生产,你使用 BarMatic 非常相似的 Stack 类,因为 barMatic 刚刚买下了你的公司。

如果您在所有地方都完全合格,您将进行大量的 grep 操作,希望您的正则表达式是正确的。 如果您使用了 using 声明,则只需修复您的(希望是共享的)头文件即可。 这样,using 声明很像“typedef int ourInt;” 或一个明显的常量或 const:“const int FOO = 1;”,因为它提供了一个位置来更改引用到多个位置的内容。 在每次使用时完全限定命名空间会消除这一好处。

相反,如果您使用 using 指令并引入所有名称空间 FooMatic,那么您的 grep 可能会更加困难,如果说管理层坚持使用 BarMatic::Foo 但您仍然必须使用 FooMatic:Baz,BarMatic 相当于 Baz 的无论什么原因都无法使用。

因此,一次引入一种类型(类、函数、常量)通常是最灵活的,也是最好的保护自己免受不可避免但未知的变化影响的方法。 与大多数编码一样,您希望最大限度地减少繁琐的重复,同时保持足够的粒度。

In C++, you /especially/ have to read the compiler error messages carefully.

Notice the first error was "error: ‘A’ is not a namespace-name". That's true, A is a classname.

using namespace Foo; // brings in  all of foo;
using Bar::Baz // brings in only Baz from Bar

You want to write:

using Test::A;

That does two good things: it brings in A for you to use, and it doesn't bring in all the rest of Test, which is good too, because you should only bring in what you need, so as to not accidentally depend on something you don't realize you're depending upon.

However, as foo is static in A, you'll still have to refer to A::foo explicitly. (Unless you do something like writing a free function that forwards to A::foo; in general, this is a bad idea if you're only doing it to save some typing.)

Some may advise not using using declarations at all, instead fully qualifying all names.

But this is (to quote Stroustrup) "tedious and error prone", and it gets in the way of refactoring: say that you fully qualify every use of class FooMatic::Stack, and then management insists, just before you're about to go to production, that you use BarMatic's very similar Stack class, because barMatic just bought out your company.

Had you fully qualified everywhere, you'd be doing a lot of grepping, hoping your regex was right. If you used a using declaration, you can just make a fix to your (hopefully shared) header file. In this way, a using declaration is a lot like a "typedef int ourInt;" or a manifest constant or const: "const int FOO = 1;", in that it provides one place to change something that's referred to many places. Fully qualifying a namespace at every use takes away that benefit.

Conversely, had you used a using directive and brought in all of Namespace FooMatic, your grep might have been even harder, if say management insisted on BarMatic::Foo but you still had to use FooMatic:Baz, the BarMatic equivalent for Baz being for whatever reason unusable.

So bringing in one type (class, function, constant) at a time is generally the most flexible, the way to best protect yourself against inevitable but as yet unknown changes. As in most coding, you want to minimize tedious repetition while keeping sufficient granularity.

就此别过 2024-07-22 18:13:41

没有办法解决这个问题,您需要为静态方法指定类名。

using namespace Test;

然后:

int answerToEverything = A::foo();

There is no way around it you need to specify the class name for static methods.

using namespace Test;

Then:

int answerToEverything = A::foo();
仄言 2024-07-22 18:13:41

不,不可能以任何优雅的方式做你想做的事情。 您能够做的最接近的事情是创建一个委托给您的函数的宏或内联函数。 然而,这两种选择都相当难看,所以我不会发布任何代码示例。 只需硬着头皮指定整个名称,或者重构代码,使静态方法只是全局函数。

No, it's not possible to do what you're trying to do in any elegant fashion. The closest thing you'll be able to do are to create a macro or an inline function which delegates to your function. However, both of these alternatives are rather ugly, so I'm not going to post any code samples. Just bite the bullet and specify the whole name, or refactor your code so that the static methods are just global functions.

↙温凉少女 2024-07-22 18:13:41

不要成为“使用命名空间”的滥用者。 使用这些命名空间!

std::cout << Test::A::foo() << std::endl;

Don't be a "using namespace" abuser. Use those namespaces!

std::cout << Test::A::foo() << std::endl;
~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文