1

我的意图是有一些基类CBaseClass,除其他外,用作某些类型成员的容器CBaseMember;然后得出一个CDerivedClass : public CBaseClass成立CDerivedMember : public CBaseMember

我不能使用一个指针并用一个对象CBaseMember初始化它,因为它是一种多重继承情况,有一个与实现无关但需要对. 很多肮脏的铸造是我非常想避免的。CDerivedMemberCDerivedClassCDerivedMemberCBaseClassCDerivedClass

我对这个问题的解决方案是制作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()由于显而易见的原因尚未解决),但不幸的是我不知道如何更改我的代码以表示我想要它的意思。

谁能解释这些事情是如何正确完成的 - 或者为我的问题提出另一种解决方案?

谢谢!

4

2 回答 2

0

我怀疑您想摆脱模板,因为您提供的代码段会起作用(如果您将class关键字添加到类型的声明中)。

如果您想避免从CBaseMember*to向下转换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,尽管它从未使用过。因此,如果内存对您很重要,那么这可能不可行。

于 2012-04-12T11:00:01.460 回答
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在访问它的成员时回退到。

于 2012-04-12T10:28:01.350 回答