2013-01-15 87 views
2

我正在围绕这个问题进行包装。我认为这实际上是不可能的,但只是为了确定我想问问在这里是否真的有解决方案。 考虑下面的代码。有2个模板类A和B以及两个分别来自A和B的非模板类C和D.模板类有两种类型,继承和前向声明

// definition of class A 
template <class DerivedA, class DerivedB> class A { 
private: 
    DerivedB data; 
public: 
    A(const DerivedB& data) : data(data) {} 
    virtual ~A() {} 
    DerivedB get() const { return data; } 
}; 

// definition of class B 
template <class DerivedA, class DerivedB> class B { 
private: 
    DerivedA data; 
public: 
    B(const DerivedA& data) : data(data) {} 
    virtual ~B() {} 
    DerivedA get() const { return data; } 
}; 

// forward declaration of D 
class D; 

// definition of class C, derives from A<C, D> 
class C : public A<C, D> { 
private: 
    int extraInfo; 
public: 
    C(const D& d) : A(d) {} 
    virtual ~C() {} 
    int getExtraInfo() const { return extraInfo; } 
}; 

// definition of class D, derives from B<C, D> 
class D : public B<C, D> { 
private: 
    int extraInfo; 
public: 
    D(const C& c) : B(c) {} 
    virtual ~D() {} 
    int getExtraInfo() const { return extraInfo; } 
}; 

这里的问题是,类C不能被定义,因为类D只是前向声明。因此,当模板A被写出时,它不知道它的私有成员的类型是什么。请注意,我无法使用指针,我需要一些已知的功能。是否有可能编译这样我有我的课程C和D?

+0

什么阻止你使用指针? – Henrik

+0

你想达到什么目的? –

+0

@YochaiTimmer我试图实现一个有向图。类A代表节点,类B代表弧。为了实际使用具有有用属性的有向图,节点和边必须从节点类和边类中派生出来。为了避开'dynamic_cast',我尝试使用这种模板化方法。 – rwols

回答

1

有解决这个问题没办法,你解释它,不应该有。当你拥有它现在:

class C : public A<C, D> 

意味着C将继承D类型的数据成员。依次为:

class D : public B<C, D> 

意味着D将继承C类型的数据成员。

如果CD,其中有一个C,其中有一个D ...你有一个很好的无限递归,在这种情况下,任何CD对象的大小将是无穷的意蕴。因此,除非您使用指针(您可以在插入适当的空指针的任何点处剪切无限长链)或引用(您可以引用先前使用的对象),否则您不能也不应该拥有这种类。

1

C继承D类型的成员,D继承C类型的成员。所以,不,这是不可能的。

0

您可以通过让C和D实现一个纯虚拟类,以及您需要的功能(包括getters),并使它们作为模板参数传递该类来摆脱这种困境。然后在A和B中实际使用指向它的指针,但是保留了所有功能。

像这样的东西(使自己适应)

// definition of class A 
template <class DerivedA, class DerivedB> class A { 
private: 
    const DerivedB& _data; 
public: 
    A(const DerivedB& data) : _data(data) {} 
    virtual ~A() {} 
    DerivedB& get() const { return data; } 
}; 

// definition of class B 
template <class DerivedA, class DerivedB> class B { 
private: 
    DerivedA data; 
public: 
    B(const DerivedA& data) : data(data) {} 
    virtual ~B() {} 
    DerivedA get() const { return data; } 
}; 

class TheInterface { 
public: 
    virtual int getExtraInfo() const = 0; 
virtual ~TheInterface() = 0; 
}; 

// definition of class C, derives from A<C, D> 
class C : public TheInterface, public A<C, TheInterface> { 
private: 
    int extraInfo; 
public: 
    C(const TheInterface& d) : A(d) {} 
    virtual ~C() {} 
    int getExtraInfo() const { return extraInfo; } 
}; 

// definition of class D, derives from B<C, D> 
class D : public TheInterface, public B<C, D> { 
private: 
    int extraInfo; 
public: 
    D(const C& c) : B(c) {} 
    virtual ~D() {} 
    int getExtraInfo() const { return extraInfo; } 
};