繁体   English   中英

部分隐藏的继承树

[英]Partially hidden inheritance tree

我有一个这样的类树:

class A;
class B : public A;

然后,我想创建一个派生于类B的类。但是我希望该派生对外部成员以及从类C继承的任何其他成员都隐藏

class C : private B;

void test() {
    C c;
    B *b = &c; // compiler error: B in C is private and is therefore not type compatible. This is desired.
}

但是,我也想揭示类A的继承。在这种情况下,隐藏类B也隐藏了类A。

void test2() {
    C c;
    A *a = &c; // Compiler error: A is only accessible through B which is not possible with a private inheritance of B. This is not desired; this conversion should be possible.
}

我可以再次从A继承,但是如果A有任何成员变量,那显然会创建重复的成员变量。 我可以创建类A的虚拟继承,但是我觉得它不会产生我想要的确切效果,因为那会影响整个树而不是这个部分(对吗?)

我想显而易见的解决方案是创建一个类型转换成员函数:

class C : private B {
    A * turn_into_A() {
        // Since B is an A and we are still in the scope of C, this will succeed
        return this;
    }
};

但是,我宁愿避免像这种情况那样的显式类型转换,

任何理智的人都可能告诉我我做错了。 他们可能是正确的。 但是我只是出于知识的缘故想知道:有没有一种方法可以在没有虚拟继承或显式成员函数的类型转换的情况下进行?

我找到了可行的解决方案:

class A {
public:
    void somethingA() {
        std::cout << "a" << std::endl;
        return;
    }
 };
class B :
    public A {
public:
    void somethingB() {
        std::cout << "b" << std::endl;
        return;
    }
};
class C :
    private B {
public:
using B::A; // While B is private (and hidden), this exposes access to B::A
    void somethingC() {
        std::cout << "c" << std::endl;
        return;
    }
};

int main(int argc, char **argv) {
    C c;
    B* b = &c; // Compiler error: cannot convert because B is private (desired)
    A* a = &c; // Okay! (required)
    c.somethingC();
    c.somethingB(); // Compiler error: private. (desired)
    c.somethingA(); // Compiler error: A is exposed, but not A's members. This can be solved by adding 'using B::A::somethingA()' in class declaration (undesired but acceptable in my situation)
    a->somethingA(); // Okay! (of course)
}

这不是完美的,因为它仅使C能够转换为A(就我的目的而言,无论如何我最终都会这样做,所以很好)。 但是,它不会直接公开A的成员以允许将C用作“ an-A”,例如,除非您还专门公开了B :: A :: somethingA,否则您不能调用c :: somethingA()。

继承描述了IS-A关系。 因此,在您的对象模型中,B IS-AA,C IS-AB。因此,为什么不使用

class C : public B { ...};

这样您就可以根据需要将C对象视为B对象以及A对象。 希望能有所帮助。

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM