继承和嵌套名称的陷阱
Pitfalls of inheritence and nested names
我在项目中设计 C++ 对象继承树时遇到了一个特殊情况。我预计以下会失败:
struct A {
protected:
struct C { };
};
struct B: A {
struct C { };
};
但是,这编译得很好。这像覆盖吗?我可以看出这不是模棱两可的,因为它们可以指定为 A::C
和 B::C
,但是这在多态情况下如何起作用?它会调用指定类型的 C 还是实例类型的 C?同样,假设下面的代码有效并且 func
存在于 C:
的两个实现中
A x = B();
decltype(x)::C::func();
哪个 C 会调用它们的函数?更一般地说,它们是描述这些代码片段如何解析的资源吗?
这很好,因为您有两个不相关的 struct C
:一个是 B::C
,另一个是 B::A::C
。 C
只是他们的快捷方式名称。
如果您在每个 C 中都定义了一个静态函数 f(),您将能够从结构外部调用它而不需要任何对象,如您的代码所示:
A a = B(); // the type of a is A (B is sliced, by the way)
decltype(a)::C::f(); // so this calls A::C::f()
现在为了完整起见,这里有一个更完善的示例,表明在任何时候都没有歧义:
struct A {
struct C { static void f() { cout << "A::C::f" <<endl; } };
};
struct B: A {
C c1; // the only C known here is A::C
struct C { static void f() { cout << "B::C::f" <<endl; }}; // now B::C hides A::C
C c2; // so here the closest C known is B::C
A::C c3; // and here I can be explicit about the C I want
using D=A::C; // and here another way to be explicit:
D c4;
};
int main() {
B b;
decltype(b.c1)::C::f(); // A
decltype(b.c2)::C::f(); // B
}
我在项目中设计 C++ 对象继承树时遇到了一个特殊情况。我预计以下会失败:
struct A {
protected:
struct C { };
};
struct B: A {
struct C { };
};
但是,这编译得很好。这像覆盖吗?我可以看出这不是模棱两可的,因为它们可以指定为 A::C
和 B::C
,但是这在多态情况下如何起作用?它会调用指定类型的 C 还是实例类型的 C?同样,假设下面的代码有效并且 func
存在于 C:
A x = B();
decltype(x)::C::func();
哪个 C 会调用它们的函数?更一般地说,它们是描述这些代码片段如何解析的资源吗?
这很好,因为您有两个不相关的 struct C
:一个是 B::C
,另一个是 B::A::C
。 C
只是他们的快捷方式名称。
如果您在每个 C 中都定义了一个静态函数 f(),您将能够从结构外部调用它而不需要任何对象,如您的代码所示:
A a = B(); // the type of a is A (B is sliced, by the way)
decltype(a)::C::f(); // so this calls A::C::f()
现在为了完整起见,这里有一个更完善的示例,表明在任何时候都没有歧义:
struct A {
struct C { static void f() { cout << "A::C::f" <<endl; } };
};
struct B: A {
C c1; // the only C known here is A::C
struct C { static void f() { cout << "B::C::f" <<endl; }}; // now B::C hides A::C
C c2; // so here the closest C known is B::C
A::C c3; // and here I can be explicit about the C I want
using D=A::C; // and here another way to be explicit:
D c4;
};
int main() {
B b;
decltype(b.c1)::C::f(); // A
decltype(b.c2)::C::f(); // B
}