2014-04-07 133 views
1

我有一个类树来:部分隐藏继承树

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; 
    } 
}; 

不过,我更愿意避免明确的类型转换,如这种情况下,

任何理智的人会告诉我,我这样做是错误的。他们可能是对的。但为了知识的缘故,我只想知道:有没有一种方法可以在没有虚拟继承或显式成员函数的类型转换的情况下执行此操作?

+0

@milleniumbug哈,错误的问题。 Apoligies。 – juanchopanza

+0

幸运的是,您留下了一个免费的朋友功能进行类型转换的可能性。 –

回答

0

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

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被用作A-A,例如,除非特别暴露B :: A :: somethingA,否则不能调用c :: somethingA()。

-1

继承描述了IS-A关系。所以,在你的对象模型,B IS-A A,C IS-A B.那么,你为什么不使用

class C : public B { ...}; 

所以,你可以查看对象C为B的对象,也是一个一个需要的对象。希望有所帮助。

+1

因为他想在B后私下继承? – zoska

+0

@zoska是的,但这是矛盾的,而私人继承你不能将它看作超类对象。否则,朋友可能会帮忙。 –

+0

因为我特别不希望它表明它是B.我试图实现的想法是,类B和C *不*实际相关...他们只是碰巧分享了很多相同的功能。所以为了减少代码重复,让其中一个或另一个从另一个继承来重新使用代码是有益的。但是,它们不相关,因此不应以任何可互换的方式使用。 – inetknght