【问题标题】:nested class inherits from nested class嵌套类继承自嵌套类
【发布时间】:2012-09-17 15:47:12
【问题描述】:

我希望 C 类从 A 类继承其虚函数,而 D 类(C 类中的嵌套类)从 B 类(A 类中的嵌套类)继承其数据字段,这就是我所拥有的。

file1.h

class A{
 public:
     virtual void foo()=0;
     class B{
       public:
         int data;
     };
};

file2.h

class C : public A{
 public:
     class D : public A::B{

     };    
};

file2.cpp

void C::foo(){//code}
C::D::D():data(0){//Bad initialization list, error being data is not a member of C::D even it should inherits from its base class
 data = 0; //good! compiler can see data is a member of A::B,and C::D inherits from it
}

我有两个问题,第一个是我正在做的正确方法来实现这种继承。其次,正如我所评论的,为什么编译器可以在手动初始化过程中看到数据来自 A::B 而不是在初始化列表中?他们不应该在同一个范围内吗?非常感谢

编辑1

所以如果类 C::D(foo) 不直接继承自 A::B(foo),而是 C 继承自 A,我的看法是,由于 C 继承自 A 及其所有公共字段,包括它的内部类 A::B(foo), D(foo) 与 A::B(foo) 具有完全相同的名称,并且是 C 的内部类,就像这样,即两个内部类都使用 foo

class A{
 public:
     class foo{
       public:
         int data;
     };
};

class C : public A{
 public:
     class foo{

     };    
};

当我直接调用 C::foo 时,编译器会不会感到困惑?因为范围内有两个具有名称的构造函数?或者它选择调用“最近的”,例如 C:foo?而不是爬上继承链?非常感谢

【问题讨论】:

  • 请提出另一个问题进行编辑,而不是编辑您的旧问题。首先,接受的答案仅适用于第一部分。您可以在新问题中引用此问题。

标签: c++ inheritance


【解决方案1】:
  1. 是的,您的方法是实现这种继承的正确方法。

  2. 初始化列表用于控制传递给构造函数的参数。您可以将参数传递给 B 的构造函数,但不能直接初始化 B 的成员(这是其构造函数的工作)。如果没有为基类或成员指定构造函数,则使用默认构造函数。 在您的情况下,将构造函数添加到 B 以实现您想要的。

    class A {
    public:
        class B{
        public:
            B(int i) : data(i) {}
            int data;
        };
    }; 
    
    class C : public A {
        class D : public A::B {
        };
    };
    
    C::D::D() :B(0) { }
    

【讨论】:

    【解决方案2】:

    句法的角度来看,它是正确的(*1)。当然,除了初始化列表。您只能在初始化列表中初始化当前类成员(而不是基类成员)。这与嵌套无关。

    class X
    {
    public: 
       int x;
    };
    class Y : X
    {
       Y() : x(0) {} //still illegal
    };
    

    我之所以说句法 POV,是因为它是一件很奇怪的事情……我确信有一种更简洁的方法可以实现你真正想要的。

    【讨论】:

    • 在你的例子中,你的意思是 Y 应该从 X 继承吗?
    【解决方案3】:

    您从嵌套类继承的语法是正确的。

    初始化列表用于初始化该类的成员;基类成员应该在基类构造函数中初始化。

    【讨论】:

      【解决方案4】:

      从句法上讲,接受的答案很好地回答了您的问题。 这是我在与机制相关的设计方面的两分钱: 在您的示例中,抽象类 A 本质上是一个接口。接口应该只定义行为和行为。话虽如此,我认为在接口中有一个嵌套类是没有意义的。

      1) 接口没有任何数据成员可供嵌套类操作,就像您的示例一样。这首先消除了对嵌套类的需要。

      2) 嵌套类不是行为。所以它不应该出现在界面中。

      现在您可能会争辩说您的示例只是一个快速演示,实际上您会有数据成员供嵌套操作,即 A 类不是纯接口。您只是想为嵌套的 B 类提供一个默认实现,让 C 类决定他想如何将 B 类自定义为他自己的 D 类。如果是这样,恐怕设计会更糟。

      3) 考虑迭代器模式。 A类本质上是一个不能被实例化的抽象容器(因为你里面有一个纯虚函数)——让我们把它映射到我们脑海中的IContainer。现在你创建了一个类 C,它有一个向量/数组实现,他自己的迭代器 D 指向数组中的某个元素。

      然后你想创建另一个类 E,它有一个哈希映射实现,她自己的迭代器 F 指针指向哈希映射中的某个对。

      这是灾难:在包含类(C,E ...)的实现中,您通常无法在所有迭代器类(D,F ...)中拥有统一的接口- 很可能(考虑赋值运算符:BIterator operator=(const BIterator& other);),D 类有一个接受 D 类对象作为参数的函数:DIterator operator=(const DIterator& other); F 类有一些函数接受 F 类对象作为参数:FIterator operator=(const FIterator& other)

      另一方面,这是行不通的,因为 DIterator 和 FIterator 都是 BIterator 的子类 - 您不能使用“更窄”(或“更具体”)参数覆盖函数,因为它违反了参数类型(C++ 不允许逆变参数,因此它需要匹配参数类型;所以从技术上讲,您可以为 F 类使用 FIterator operator=(const BIterator& other) 并执行从 BIterator 到 FIterator 的运行时动态转换——但这很丑陋,而且不会感觉:一个具体的苹果有一个赋值运算符,它为自己分配一个抽象的“水果”)。你只是让自己陷入了两难境地。

      综上所述,由于 1) 2) 和 3) 的原因,请不要在接口/抽象基类中包含嵌套类。 迭代器模式只是一个示例,可以只要嵌套的类与包含的类交互,就会有很多场合让你自责。如果没有,那么一开始就没有嵌套类。

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 2011-06-19
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2013-05-04
        • 1970-01-01
        • 1970-01-01
        相关资源
        最近更新 更多