【问题标题】:C++ Using two variables of same name in Derived and Base classesC++ 在派生类和基类中使用两个同名变量
【发布时间】:2013-07-09 15:34:08
【问题描述】:

我之前已经发布过这个问题 (Here),这是一种不同的解决方案。这个解决方案似乎更好地封装了那些实现类的行为,因为它可以防止他们需要显式地向上转换。

问题来了:

我有一个项目,我想在其中隔离大多数对象中的核心行为,同时通过派生对象提供其他行为。很简单:

class BaseA
{
    virtual void something() {}
}


class DerivedA : public BaseA
{
    void something() {}
    void somethingElse() {}
}

现在假设我还有第二组类,相同的继承方案,只是它们聚合了上述类。但是,我希望基版本使用基类,派生版本在派生类中。我的解决方案是考虑使用相同的名称“隐藏”基类变量;

class BaseB
{
    BaseA *var;

    BaseB()
    {
        var = new BaseA();
    }

    virtual void anotherThing1();
    virtual void anotherThing2();
    virtual void anotherThing3();
}

class DerivedB : public BaseB
{
    DerivedA *var;

    DerivedB()
    {
        var = new DerivedA();
    }

    void anotherThing1();
    void anotherThing2();
    void anotherThing3();
    void andAnother1();
    void andAnother2();
}

这种方法的目标是让依赖于派生聚合类的函数不再需要显式转换来实现获得的功能。

void func1( BaseB &b )
{
    b.anotherThing1();
    b.var->something();
}

void func2( DerivedB &b )
{
    b.anotherThing1();
    b.andAnother1();
    b.var->something();
    b.var->somethingElse();
}

void main( int argc, char **argv )
{
    BaseB    baseB;
    DerivedB derivedB;

    func1( baseB );
    func1( derivedB );
    func2( derivedB );
}

这会被认为是不好的做法吗?

【问题讨论】:

  • 你为什么要这样做? Base* var 不会为他们俩做吗?如果不是,你为什么要它们同名——这是故意阻止其他人能够阅读代码还是什么?
  • 我只是想获得有关这种方法的输入。我最初想只使用一个 Base *var(我的帖子开头的链接)。但是想知道这对于那些实现类的人来说是否更容易,因为他们永远不需要为派生功能显式转换

标签: c++ class inheritance casting polymorphism


【解决方案1】:

这会被认为是不好的做法吗?

是的,这是不好的做法,因为 Base 中的 var 将未被使用。看起来 DerivedB 不应该派生自 BaseB:相反,它们应该派生自同一个抽象基类,如下所示:

class AbstractB {
public:
    virtual void anotherThing1() = 0;
    virtual void anotherThing2() = 0;
    virtual void anotherThing3() = 0;
};
class DerivedB1 : public AbstractB { // Former BaseB
    BaseA *var;

public:
    DerivedB1() {
        var = new BaseA();
    }
    virtual void anotherThing1();
    virtual void anotherThing2();
    virtual void anotherThing3();
};
class DerivedB2 : public AbstractB { // Former DerivedB
    DerivedA *var;
public:
    DerivedB2() {
        var = new DerivedA();
    }
    void anotherThing1();
    void anotherThing2();
    void anotherThing3();
    void andAnother1();
    void andAnother2();
};

这里使用的一般原则是,您应该尝试将继承层次结构中的所有非叶类抽象化。

【讨论】:

  • 是的,我希望不要使用这种模式,因为派生类中几乎每个被覆盖的函数都只是简单地调用基本版本,然后运行一些额外的行。所以通过完全分离类,会有很多代码重复。
  • @Pondwater 您可以将共享功能移动到抽象类中,派生类提供对逻辑的特定调整。请参阅Template Method 模式(与 C++ 模板无关)。
  • 共享功能依赖于聚合对象。所以在我的情况下 anotherThing#() 需要 var 属性。 DerivedB2 将要求 var 为 DerivedA。
  • @Pondwater 您可以尝试对 BaseA/DerivedA 对应用相同的重构:使用虚函数使 DerivedB1DerivedB2 仅根据 @ 的基本功能工作987654331@(即调用相同,但由于多态性,实际函数将基于运行时类型)。这应该统一部分DerivedB1/DerivedB2 代码。将不可统一的代码放入DerivedB1/DerivedB2 virtuals,从抽象库中调用,完成模板方法实现。
猜你喜欢
  • 2018-05-19
  • 2018-01-20
  • 1970-01-01
  • 2022-11-28
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2015-08-16
相关资源
最近更新 更多