模板类继承语法

时间:2012-04-12 10:08:35

标签: c++

我的目的是建立一些基类CBaseClass,其中包括CBaseMember类型成员的容器;然后导出一个CDerivedClass : public CBaseClass,其中包含CDerivedMember : public CBaseMember

我无法使用指向CBaseMember的指针并使用CDerivedMember中的CDerivedClass对象对其进行初始化,因为它是一个多重继承的情况,CDerivedMember有一个额外的接口(纯粹的抽象基类,与CBaseClass实现无关,但需要CDerivedClass可见。很多肮脏的铸造是我非常想避免的。

我解决这个问题的方法是让CBaseClass成为一个模板,如下所示:

//declaration
template <class Member>
CBaseClass
{
protected:
    virtual void GenericMethod();
    virtual void VirtualMethod() = 0;

    Member* member;
};

//definition
template <class Member>
void CBaseClass<Member>::GenericMethod()
{
    member->SomeMemberMethod();
}

然后从中继承CDerivedClass,如下所示:

//declaration
CDerivedClass : public CBaseClass<CDerivedMember>
{
protected:
    virtual void VirtualMethod();
};

//definition
void CDerivedClass::VirtualMethod()
{
    member->SomeDerivedMethod();
}

可以预见,这不起作用(CBaseClass<CDerivedMember>::GenericMethod()由于不明原因而未解决),但遗憾的是我不知道如何更改我的代码以表示我想要它的含义。

任何人都可以解释一下这些事情是如何正确完成的 - 或者为我的问题提出另一种解决方案吗?

谢谢!

2 个答案:

答案 0 :(得分:0)

好吧,你可以将脏的类型转换保存在一个地方,封装在你的班级中。因此,它不再那么脏了。

class CBaseMember {
public:
    virtual void SomeMemberMethod(){}
};

class CDerivedMember : public CBaseMember {
public:
    virtual void SomeMemberMethod() { /* do other stuff */ }
    virtual void SomeDerivedMethod() {}
};

//declaration
class CBaseClass
{
protected:
    virtual void GenericMethod();
    virtual void VirtualMethod() = 0;

    CBaseMember* member;
    virtual CBaseMember * getMember() {
    return member;
    }
};

//definition
void CBaseClass::GenericMethod()
{
    getMember()->SomeMemberMethod();
}

//declaration
class CDerivedClass : public CBaseClass
{
protected:
    virtual void VirtualMethod();
    virtual CDerivedMember * getMember() {return static_cast<CDerivedMember *>(member);}
};

//definition
void CDerivedClass::VirtualMethod()
{
    getMember()->SomeDerivedMethod();
}

总之,您在派生类的getMember()方法中执行脏类型转换。此时,您应确保该成员的类型无论如何都是CDerivedMember。因此,只要您知道您拥有的指针属于CDerivedClass类型,就可以访问其CDerivedMember而无需进行类型转换。如果你必须回到CBaseClass指针,那么在访问其成员时你自然会回到CBaseMember

答案 1 :(得分:0)

我怀疑您想摆脱模板,因为您提供的代码段可以使用(如果您在类型声明中添加了class关键字)。

如果您想避免从CBaseMember*CDerivedMember*投降,您可以通过动态绑定和协方差来处理这种情况

class CBaseClass {
  private:
    CBaseMember* const baseMember;
  protected:
    virtual CBaseMember* member() const {
    //      ^^^^^^^^^^^
      return baseMember;
    }
    /* everything else you need here. Just never ever access `baseMember` directly */
};
class CDerivedClass : public CBaseClass {
  private:
    CDerivedMember* const derivedMember;
  protected:
    virtual CDerivedMember* member() const {
    //      ^^^^^^^^^^^^^^
      return derivedMember;
    }
    /* everything else you need here. Just never ever access `derivedMember` directly */
};

但是,这只有在您永远不会将成员更改为指向其他位置的情况下才有效,因为您无法使用setter来提取此技巧:virtual void CBaseClass::member(CBaseMember*)无法使用virtual void CDerivedClass::member(CDerivedMember*)覆盖。

请注意,您仍会在baseMember周围携带CDerivedClass指针,但它永远不会被使用。因此,如果记忆对你很重要,那么这可能是不可行的。