嵌套类继承自嵌套类

时间:2012-09-17 15:47:12

标签: c++ inheritance

我希望类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而不是初始化列表中的数据?它们不应该在同一范围内吗?非常感谢你

EDIT1

因此,如果类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?而不是爬上继承链?非常感谢你

4 个答案:

答案 0 :(得分:2)

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

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

我说语法POV,因为这是一个奇怪的事情......我确信有一种更清洁的方式来实现你真正想要的东西。

答案 1 :(得分:2)

  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)

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

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

答案 3 :(得分:0)

从语法上讲,接受的答案很好地回答了你的问题。 这是与机制相关的设计方面的两分钱: 在您的示例中,抽象类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),不要在接口/抽象基类中包含嵌套类。迭代器模式只是一个例子,只要嵌套类与包含的类交互,就有很多场合可以让你自己站起来。如果没有,那么首先在嵌套类中没有意义。