从成员复制方法

发布于 2024-11-05 21:20:42 字数 755 浏览 6 评论 0原文

我有一个简单的低级容器类,由更高级的文件类使用。基本上,文件类在将最终版本保存到实际文件之前使用容器在本地存储修改。因此,某些方法直接从容器类转移到文件类。 (例如,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.
    }
}

I have a simple, low-level container class that is used by a more high-level file class. Basically, the file class uses the container to store modifications locally before saving a final version to an actual file. Some of the methods, therefore, carry directly over from the container class to the file class. (For example, Resize().)

I've just been defining the methods in the file class to call their container class variants. For example:

void FileClass::Foo()
{
    ContainerMember.Foo();
}

This is, however, growing to be a nuisance. Is there a better way to do this?

Here's a simplified example:

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.
    }
}

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(5

浅紫色的梦幻 2024-11-12 21:20:42

那么,为什么不直接从 MyContainer 继承并公开那些您想要通过 using 声明转发的函数呢?这就是所谓的“根据MyContainer实现MyClass”。

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 没有虚拟析构函数,则为非多态。

Well, why not just inherit privatly from MyContainer and expose those functions that you want to just forward with a using declaration? That is called "Implementing MyClass in terms of 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();
      // ...
    }
}

Now the "outside" will be able to directly call Foo, while Bar is only accessible inside of MyClass. If you now make a function with the same name, it hides the base function and you can wrap base functions like that. Of course, you now need to fully qualify the call to the base function, or you'll go into an endless recursion.


Additionally, if you want to allow (non-polymorphical) subclassing of MyClass, than this is one of the rare places, were protected inheritence is actually useful:

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

Non-polymorphical if your MyClass has no virtual destructor.

滥情稳全场 2024-11-12 21:20:42

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

但这通常并不困难,除非您需要支持数十个函数、覆盖和模板。

我通常这样写:

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

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

Yes, maintaining a proxy class like this is very annoying. Your IDE might have some tools to make it a little easier. Or you might be able to download an IDE add-on.

But it isn't usually very difficult unless you need to support dozens of functions and overrides and templates.

I usually write them like:

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

It's nice and symmetrical. C++ lets you return void values in void functions because that makes templates work better. But you can use the same thing to make other code prettier.

意中人 2024-11-12 21:20:42

这就是 委托继承,我不知道 C++ 是否提供了任何机制来帮助实现这一点。

That's delegation inheritance and I don't know that C++ offers any mechanism to help with that.

过潦 2024-11-12 21:20:42

考虑在您的情况下什么是有意义的 - MyClass 和 MyContainer 之间的组合(具有)或继承(是)关系。

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

如果有疑问,你所拥有的可能没问题。

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

Consider what makes sense in your case - composition (has a) or inheritance (is a) relationship between MyClass and MyContainer.

If you don't want to have code like this anymore, you are pretty much restricted to implementation inheritance (MyContainer as a base/abstract base class). However you have to make sure this actually makes sense in your application, and you are not inheriting purely for the implementation (inheritance for implementation is bad).

If in doubt, what you have is probably fine.

EDIT: I'm more used to thinking in Java/C# and overlooked the fact that C++ has the greater inheritance flexibility Xeo utilizes in his answer. That just feels like nice solution in this case.

冰雪之触 2024-11-12 21:20:42

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

但这个问题的真正问题是该类没有行为。它只是一个不执行任何操作的包装器。每个类都需要做一些事情,而不仅仅是传递数据。

关键是每个类都有正确的接口。这个需求就需要编写转发函数。每个成员函数的主要目的是将所需的工作分配给所有数据成员。如果您只有一个数据成员,并且您还没有决定该类应该做什么,那么您所拥有的只是转发函数。一旦您添加更多成员对象并决定该类应该做什么,那么您的转发功能将更改为更合理的东西。

对此有帮助的一件事是保持班级规模较小。如果接口很小,那么每个代理类只会有很小的接口,并且接口不会经常更改。

This feature that you need to write large amounts of code is actually necessary feature. C++ is verbose language, and if you try to avoid writing code with c++, your design will never be very good.

But the real problem with this question is that the class has no behaviour. It's just a wrapper which does nothing. Every class needs to do something other than just pass data around.

The key thing is that every class has correct interface. This requirement makes it necessary to write forwarding functions. The main purpose of each member function is to distribute the work required to all data members. If you only have one data member, and you've not decided yet what the class is supposed to do, then all you have is forwarding functions. Once you add more member objects and decide what the class is supposed to do, then your forwarding functions will change to something more reasonable.

One thing which will help with this is to keep your classes small. If the interface is small, each proxy class will only have small interface and the interface will not change very often.

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文