会员复制方法

时间:2011-05-09 23:20:40

标签: c++ oop inheritance methods class-design

我有一个简单的低级容器类,由更高级别的文件类使用。基本上,在将最终版本保存到实际文件之前,文件类使用容器在本地存储修改。因此,某些方法直接从容器类传递到文件类。 (例如,Resize()。)

我刚刚在文件类中定义方法来调用它们的容器类变体。例如:

void FileClass::Foo()
{
    ContainerMember.Foo();
}
但是,这种情况越来越令人讨厌。有更好的方法吗?

这是一个简化的例子:

class MyContainer
{
    // ...

    public:

    void Foo()
    {
        // This function directly handles the object's
        // member variables.
    }
}

class MyClass
{
    MyContainer Member;

    public:

    void Foo()
    {
        Member.Foo();

        // This seems to be pointless re-implementation, and it's
        // inconvenient to keep MyContainer's methods and MyClass's
        // wrappers for those methods synchronized.
    }
}

5 个答案:

答案 0 :(得分:7)

那么,为什么不直接从MyContainer继承并通过using声明公开那些你想要转发的函数呢?这被称为“根据 MyClass实施MyContainer

class MyContainer
{
public:
    void Foo()
    {
        // This function directly handles the object's
        // member variables.
    }

    void Bar(){
      // ...
    }
}

class MyClass : private MyContainer
{
public:
    using MyContainer::Foo;

    // would hide MyContainer::Bar
    void Bar(){
      // ...
      MyContainer::Bar();
      // ...
    }
}

现在,“外部”可以直接拨打Foo,而Bar只能在MyClass内访问。如果你现在创建一个具有相同名称的函数,它会隐藏基函数,你可以像这样包装基函数。当然,您现在需要完全限定对基本函数的调用,否则您将进行无休止的递归。


此外,如果你想允许(非多态)子类MyClass,这是一个罕见的地方,受保护的继承实际上是有用的:

class MyClass : protected MyContainer{
  // all stays the same, subclasses are also allowed to call the MyContainer functions
};

如果您的MyClass没有虚拟析构函数,则为非多态。

答案 1 :(得分:1)

是的,维护这样的代理类非常烦人。您的IDE可能有一些工具可以使它更容易一些。或者您也可以下载IDE插件。

但除非您需要支持许多功能和覆盖以及模板,否则通常不会非常困难。

我通常把它们写成:

void Foo()      { return Member.Foo(); }
int  Bar(int x) { return Member.Bar(x); }

它很好而且对称。 C ++允许您在void函数中返回void值,因为这样可以使模板更好地工作。但是你可以使用相同的东西来使其他代码更漂亮。

答案 2 :(得分:1)

那是delegation inheritance而且我不知道C ++提供了任何帮助它的机制。

答案 3 :(得分:1)

考虑一下你的案例中有意义的事情 - MyClass和MyContainer之间的组合(拥有)或继承(是a)关系。

如果你不想再拥有这样的代码,你几乎只限于实现继承(MyContainer作为基类/抽象基类)。但是,您必须确保在您的应用程序中实际上这是有意义的,并且您不是纯粹为了实现而继承(实现的继承很糟糕)。

如果有疑问,你所拥有的可能很好。

编辑:我更习惯于在Java / C#中思考并且忽略了这样一个事实:C ++在他的答案中使用了更大的继承灵活性。在这种情况下,这感觉就像是一个很好的解决方案。

答案 4 :(得分:0)

您需要编写大量代码的此功能实际上是必需的功能。 C ++是一种冗长的语言,如果你试图避免用c ++编写代码,你的设计将永远不会很好。

但这个问题的真正问题在于班级没有行为。它只是一个什么都不做的包装。除了传递数据外,每个班级都需要做一些事情。

关键是每个班级都有正确的界面。此要求使得必须编写转发功能。每个成员函数的主要目的是分发所有数据成员所需的工作。如果您只有一个数据成员,并且您还没有确定该类应该做什么,那么您所拥有的只是转发功能。一旦你添加了更多的成员对象并决定了该类应该做什么,那么你的转发功能将变为更合理的东西。

有助于此的一件事是让你的课程变小。如果接口很小,每个代理类只有很小的接口,接口不会经常改变。