我希望类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?而不是爬上继承链?非常感谢你
答案 0 :(得分:2)
从语法的角度来看,它是正确的(* 1)。当然,除了初始化列表。您只能初始化初始化列表中的当前类成员(而不是基类成员)。这与嵌套无关。
class X
{
public:
int x;
};
class Y : X
{
Y() : x(0) {} //still illegal
};
我说语法POV,因为这是一个奇怪的事情......我确信有一种更清洁的方式来实现你真正想要的东西。
答案 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),不要在接口/抽象基类中包含嵌套类。迭代器模式只是一个例子,只要嵌套类与包含的类交互,就有很多场合可以让你自己站起来。如果没有,那么首先在嵌套类中没有意义。