【问题标题】:Pitfalls of inheritence and nested names继承和嵌套名称的陷阱
【发布时间】:2019-03-23 22:51:45
【问题描述】:

我在项目中设计 C++ 对象继承树时遇到了一个特殊情况。我预计以下会失败:

struct A {
    protected:
    struct C { };
};

struct B: A { 
    struct C { };
};

但是,这编译得很好。这像覆盖吗?我可以看到这不是模棱两可的,因为它们可以指定为A::CB::C,但是这在多态情况下如何起作用?它会调用指定类型的 C 还是实例类型的 C?如,假设下面的代码有效并且func 存在于 C 的两个实现中:

A x = B();
decltype(x)::C::func();

哪个 C 会调用它们的函数?更一般地说,它们是描述像这样的代码 sn-ps 如何解析的资源吗?

【问题讨论】:

  • 您的示例将x 创建为具有A 类型(并切片B 以对其进行初始化)。在下一条语句中,x 是通过切片 B 来初始化的,这无关紧要,因为它的类型是 A。所以decltype(x)::C::func() 将解析为A::C::func()(然后根据使用的访问控制和上下文进行编译或不编译)。
  • @彼得。这就说得通了。如果A x = B(); 改为B x = B(); A &y = x; 会怎样?这也会导致切片吗?
  • B x = B() 不会导致切片(它相当于B x 没有临时[假设复制对象会创建一个相等的对象等])。 y 将能够访问 A::C 但不能访问 B::C。给定对A 的引用,编译器没有任何信息允许它隐式访问B 中的任何名称,即使引用的对象实际上是B。给定 B(或对 B 的引用),B 中的名称 C 将名称 C 隐藏在 A 中 - 只能使用特定范围访问 As C (如B::CB::A::C 或(在B 的成员内)A::C)。
  • @Peter 这就是我所期待的。谢谢:)
  • 运行时多态性在...运行时起作用。名称在编译时绑定。类型名称没有运行时多态性。

标签: c++ class oop inheritance name-lookup


【解决方案1】:

这很好,因为您有两个不相关的struct C:一个是B::C,另一个是B::A::CC 只是他们的快捷方式名称。

如果您在每个 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  
}

online demo

【讨论】:

  • 所以作为类型它们不会有命名冲突,但是你认为这会导致某种方式的意外行为吗?
  • @AnthonyMonterrosa 不,我认为这不会产生意外行为。类型的选择总是在编译时完成,而不是在运行时。如果你声明一个 C 对象,编译器必须知道 C 的含义(例如,为了生成为对象保留足够空间并构造它的代码)。
  • 我明白了。感谢您提供全面的示例!看到边缘情况有很大帮助。知道它总是编译时间也强化了我已经知道的语义。
猜你喜欢
  • 1970-01-01
  • 2014-07-11
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2013-05-04
  • 1970-01-01
相关资源
最近更新 更多