继承是否也会自动从其父级“继承”命名空间?

Does inheritance also automatically "inherit" namespaces from its parent?

提问人:Ninja 提问时间:8/30/2019 最后编辑:Vlad from MoscowNinja 更新时间:8/30/2019 访问量:2675

问:

只是想问一些关于命名空间的一般问题。如果类 A 继承了类 B 并且没有显式引用 () B 的命名空间,我是否必须在调用代码中显式命名空间才能从 A 的实例调用 B 的方法?这种语言是否依赖于(C#、C++)?usingusing B

例如,在 C# 中:

// Namespace X
class A : B 
{
    public void methodA(){...}
}

// Namespace Y
class B
{
    public void methodB(){...}
}

在其他使用 A 的代码中:

using X;
// do I need using Y?
...
A obj = new A();
obj.methodB(); // calls methodB() using instance of A
...
C# C++ 命名空间 argument-dependent-lookup using-directives

评论

1赞 cdhowie 8/30/2019
我们都对你的问题给出了如此不同的答案,这一事实说明了你的问题非常模糊,容易被误解。我们都以不同的方式解释它。你能把你的问题说得更清楚吗?
1赞 15ee8f99-57ff-4f92-890c-b56153 8/30/2019
@Ninja 请展示代码,以证明您所指的内容。“使用对象 A”是模棱两可的。你是如何“使用”对象 A 的?无论如何,这与什么有什么关系?using
2赞 Ted Lyngmo 8/30/2019
我建议您删除一个语言标签(并可能为该语言提出单独的问题)。然后,您可以比较答案以找出是否存在差异。
1赞 HolyBlackCat 8/30/2019
泰德·林莫(Ted Lyngmo)说。请一次询问一种语言。
1赞 Ninja 8/30/2019
@TedLyngmo 当然,很抱歉造成混乱。

答:

1赞 cdhowie 8/30/2019 #1

类不继承命名空间。 仅将命名空间中的符号导入到当前源文件中。它对你的班级本身没有影响。using

以下 C# 代码:

using System;

public class A {
    public void Run() {
        Console.WriteLine("Foobar");
    }
}

无论是在发出的 CIL 中,还是在用户将如何使用或派生该类的方式中,其效果都与以下代码完全相同:A

public class A {
    public void Run() {
        System.Console.WriteLine("Foobar");
    }
}

假设我们导入一个从方法返回的类型:

using System.IO;

public class A {
    public Stream createStream() {
        // implementation irrelevant
    }
}

如果我们随后在另一个源文件中声明,则该方法被继承,并且它仍然返回 ,即使声明的源文件 B 没有 using System.IO,并且 class 的用户不需要导入即可使用 ;系统知道完全合格的类型是 。class B : AcreateStream()System.IO.StreamBSystem.IOcreateStream()System.IO.Stream

public class B : A {
    public void doSomethingWithStream() {
        // We can use a System.IO.Stream object without importing System.IO
        using (var s = createStream()) {
        }
    }
}

public class C {
    public static void doSomethingElseWithStream(B b) {
        // As can other stuff that uses B.
        using (var s = b.createStream()) {
        }
    }
}

评论

0赞 Ninja 8/30/2019
感谢您的有用回复。我理解你的意思,我想我对何时需要明确定义使用有点困惑。如果 A 是 B 的子类,我猜 A 居住的命名空间需要引用 B 居住的命名空间吗?如果不是这样,那么当用户创建 A 的对象并直接调用 B 的方法(没有完整的命名空间)时,他需要引用这两个命名空间?
0赞 cdhowie 8/30/2019
@Ninja 如果 A 是 B 的子类,则该类的用户不需要知道 B 可能引用或不引用哪些命名空间。B 类中定义的所有公共符号均由 A 继承。导入到定义文件 B 中的命名空间不会继承,但这并不重要。
0赞 Ninja 8/30/2019
我想我不明白,你刚才提到类不继承命名空间......因此,A 不会知道 B 使用/引用的命名空间。
0赞 πάντα ῥεῖ 8/30/2019
@Ninja “因此,A 不会知道 B 使用/引用的命名空间。”不是天生的。
1赞 cdhowie 8/30/2019
@Ninja 没错。但是,例如,在 B 上声明的由 A 继承的方法中返回值的类型也将存在于 A 中,但在 B 源文件中如何引用该类型是完全无关紧要的。导入命名空间只是对类 B 的开发者来说是一种方便;它实际上并没有改变 B 类的任何事情。
0赞 Djuro 8/30/2019 #2

不,没有继承的命名空间这样的东西。 命名空间没有任何可以派生/继承的内容。

如果要继承不同命名空间中的类 A,则需要添加“using namespace ...”

评论

0赞 Ninja 8/30/2019
啊,你是说如果 A 继承了 B,那么 A 本身的命名空间需要 B 所在的命名空间。因此,如果是这种情况,则无需编写我的调用代码。我只需要这样做,因为命名空间 X 已经引用了命名空间 Y。这是你的意思吗?usingusing Yusing X
0赞 Djuro 8/30/2019
哦,如果你有一个来自命名空间 A 的类,它派生自命名空间 B 中的类,那么在类定义中,你需要使用 B。如果您位于命名空间 C 中,并且使用命名空间 A,则可以使用派生自命名空间 B 的类。但这并不意味着您可以使用命名空间 B 中的所有内容,而只能使用派生自的类。
2赞 ustulation 8/30/2019 #3

如果在命名空间和 中,则不能执行AXBY

// Namespace X
class A : B 
{
...
};

您需要做:

class A : Y::B 
{
...
};

所以你看你必须使用资格继承,那里没有什么特别的事情发生。顺便说一句,这是在C++中。B

如果需要更多的东西,它需要同样限定它。AY

任何使用的人都需要用它来限定它或导入所有内容,或者只是,取决于使用它 - 或 .不过,这对内部事物的可见性没有影响。AX::AAusing X::A;using namespace X;Y

唯一可能让您感到惊讶的是 Koenig Lookup,所以也许可以阅读一下。

评论

0赞 Ninja 8/30/2019
谢谢你的信息!啊,我用 C# 写了我的示例,也许 C++ 中的语法不同。@ustulation除了更改之外,在我的调用代码中,我还需要显式定义从对象 A 调用类 B 中的方法?class A : Y::Busing Y
0赞 ustulation 8/30/2019
不,现在你可以看到(好吧,它是实例内部的一个子对象,所以最好是:))。您可以调用静态和非静态内存。函数 from mem 函数,没有任何命名空间限定。BABAY
2赞 Vlad from Moscow 8/30/2019 #4

C++ (和 C#) 中的类不会继承任何命名空间。但是,由于 ADL(参数相关查找),您可以从基类的命名空间中“继承”某些名称。

这是一个示范程序

#include <iostream>

namespace N1
{
    struct A {};

    void f( const A & )
    {
        std::cout << "N1::f( const A & )\n" << '\n';
    }
}

namespace N2
{
    struct B : N1::A
    {
        B() { f( *this ); }
    };
}

int main() 
{
    N2::B b;

    return 0;
}

它的输出是

N1::f( const A & )

若要“继承”命名空间,可以在命名空间或块作用域中使用 using 指令。例如

namespace N1
{
    struct A {};
}

namespace N2
{
    using namespace N1;

    struct B : A
    {
    };
}

请注意,您不能在类作用域中使用 using 指令。

或者,您可以通过 using 声明仅引入某些名称。

评论

0赞 Ninja 8/30/2019
所以你是说在你的代码中没有必要,但可以添加?这是特定于 C++ 的吗?using namespace N1;
1赞 Vlad from Moscow 8/30/2019
@Ninja 在第一个示例中,我在 dericved 类声明 struct B 中使用了限定名:N1::A。在这种情况下,不需要 using 指令。此外,如果 ADL 可以找到非限定名称,则不需要 using 指令,就像函数 f 一样。在第二个示例中,由于 using 指令使用命名空间 N1;我可以使用基类的非限定名称。
0赞 Ninja 8/30/2019
啊,所以区别在于:合格名称与不合格名称。感谢您对 C++ 的回应,我想知道 C# 是否也是如此。
0赞 Vlad from Moscow 8/30/2019
@Ninja 是的,C# 也是如此。只是没有 ADL。