如何为 c++ 赋予属性类(接口)

发布于 2024-09-03 05:15:29 字数 1648 浏览 2 评论 0原文

我构建了几个类(ABC...),它们在同一个 BaseClass 上执行操作。示例:

struct BaseClass {
    int method1();
    int method2();
    int method3();
}
struct A { int methodA(BaseClass& bc) { return bc.method1(); } }
struct B { int methodB(BaseClass& bc) { return bc.method2()+bc.method1(); } }
struct C { int methodC(BaseClass& bc) { return bc.method3()+bc.method2(); } }

但正如您所看到的,每个类 ABC... 仅使用 的可用方法的子集code>BaseClass 并且我想将 BaseClass 分成几个块,以便清楚它使用了什么和没有使用什么。例如,解决方案可能是使用多重继承:

// A uses only method1()
struct InterfaceA { virtual int method1() = 0; }
struct A { int methodA(InterfaceA&); }

// B uses method1() and method2()
struct InterfaceB { virtual int method1() = 0; virtual int method2() = 0; }
struct B { int methodB(InterfaceB&); }

// C uses method2() and method3()
struct InterfaceC { virtual int method2() = 0; virtual int method3() = 0; }
struct C { int methodC(InterfaceC&); }

问题是每次添加新类型的操作时,我都需要更改 BaseClass 的实现。例如:

// D uses method1() and method3()
struct InterfaceD { virtual int method1() = 0; virtual int method3() = 0; }
struct D { int methodD(InterfaceD&); }

struct BaseClass : public InterfaceA, public InterfaceB, public InterfaceC
// here I need to modify the existing code to add class D
{ ... }

你知道我可以做到这一点的干净方法吗?

感谢您的帮助

编辑:

我忘了提及它也可以使用模板来完成。但我也不喜欢这个解决方案,因为所需的接口没有明确出现在代码中。您必须尝试编译代码以验证所有必需的方法是否已正确实现。另外,它需要实例化不同版本的类(每个 BaseClass 类型模板参数一个),而这并不总是可能或不需要的。

I have built several classes (A, B, C...) which perform operations on the same BaseClass. Example:

struct BaseClass {
    int method1();
    int method2();
    int method3();
}
struct A { int methodA(BaseClass& bc) { return bc.method1(); } }
struct B { int methodB(BaseClass& bc) { return bc.method2()+bc.method1(); } }
struct C { int methodC(BaseClass& bc) { return bc.method3()+bc.method2(); } }

But as you can see, each class A, B, C... only uses a subset of the available methods of the BaseClass and I'd like to split the BaseClass into several chunks such that it is clear what it used and what is not. For example a solution could be to use multiple inheritance:

// A uses only method1()
struct InterfaceA { virtual int method1() = 0; }
struct A { int methodA(InterfaceA&); }

// B uses method1() and method2()
struct InterfaceB { virtual int method1() = 0; virtual int method2() = 0; }
struct B { int methodB(InterfaceB&); }

// C uses method2() and method3()
struct InterfaceC { virtual int method2() = 0; virtual int method3() = 0; }
struct C { int methodC(InterfaceC&); }

The problem is that each time I add a new type of operation, I need to change the implementation of BaseClass. For example:

// D uses method1() and method3()
struct InterfaceD { virtual int method1() = 0; virtual int method3() = 0; }
struct D { int methodD(InterfaceD&); }

struct BaseClass : public InterfaceA, public InterfaceB, public InterfaceC
// here I need to modify the existing code to add class D
{ ... }

Do you know a clean way I can do this?

Thanks for your help

edit:

I forgot to mention that it can also be done with templates. But I don't like this solution either because the required interface does not appear explicitly in the code. You have to try to compile the code to verify that all required methods are implemented correctly. Plus, it would require to instantiate different versions of the classes (one for each BaseClass type template parameter) and this is not always possible nor desired.

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

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

发布评论

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

评论(3

落墨 2024-09-10 05:15:29

使用模式 适配器

struct InterfaceA { virtual int method1() = 0; }

struct A { int methodA(InterfaceA& bc) { return bc.method1(); } }

struct BaseClassAdapterForA: public InterfaceA 
{ 
   BaseClassAdapterForA(BaseClass& _bc) : bc(_bc) {}
   virtual int method1() 
   { 
       //note that the name of BaseClass method 
       //can be anything else
        return bc.method1(); 
        // or return bc.whatever();
   }
private:
   BaseClass& bc;
};
//usage
BaseClass bc;
A a;
BaseClassAdapterForA bca(bc);
a.methodA(bca);

use pattern Adapter

struct InterfaceA { virtual int method1() = 0; }

struct A { int methodA(InterfaceA& bc) { return bc.method1(); } }

struct BaseClassAdapterForA: public InterfaceA 
{ 
   BaseClassAdapterForA(BaseClass& _bc) : bc(_bc) {}
   virtual int method1() 
   { 
       //note that the name of BaseClass method 
       //can be anything else
        return bc.method1(); 
        // or return bc.whatever();
   }
private:
   BaseClass& bc;
};
//usage
BaseClass bc;
A a;
BaseClassAdapterForA bca(bc);
a.methodA(bca);
偏闹i 2024-09-10 05:15:29

我认为不使用其基类的某些元素的派生类没有任何问题。

派生类不需要也不应该使用其可用的一切

因此,我认为您的原始实现没有任何问题,并且无需重构它。

I see nothing wrong with a derived class that does not use some elements of its base class.

A derived class is not, and should not be, required to use everything available to it.

Hence, I see nothing wrong with your original implementation, and no need to refactor it.

虚拟世界 2024-09-10 05:15:29

methodA、methodB... 的调用者是否应该知道实际使用了方法 1、2、3 中的哪一个?

如果这样做,您可以将 BaseClass 拆分为 3 个不同的接口,并准确添加方法 1、2 和 3 所需的接口参数,如下所示:

class Interface1 {virtual int method1() = 0;};
class Interface2 {virtual int method2() = 0;};
class Interface3 {virtual int method3() = 0;};

class A
   {
   int methodA(Interface1 &i1)
      {
      return i1.method1();
      }
   };

class B
   {
   int methodB(Interface1 &i1, Interface2 &i2)
      {
      return i1.method1() + i2.method2();
      }
   };

class C
   {
   int methodC(Interface2 &i2, Interface3 &i3)
      {
      return i2.method2() + i3.method3();
      }
   };

调用者仍然可以选择从多个接口继承,如下所示:

class MyClass : public Interface2, public Interface3
   {
   int method2() {...}
   int method3() {...}
   };
...
MyClass myClass;
C c;
c.methodC(myClass,myClass);

Should the callers of methodA, methodB, ... know which of the methods 1,2,3 are actually used?

If they do, you could split up the BaseClass in 3 different interfaces, and add exactly the interface arguments needed by the methods 1, 2 and 3, like this:

class Interface1 {virtual int method1() = 0;};
class Interface2 {virtual int method2() = 0;};
class Interface3 {virtual int method3() = 0;};

class A
   {
   int methodA(Interface1 &i1)
      {
      return i1.method1();
      }
   };

class B
   {
   int methodB(Interface1 &i1, Interface2 &i2)
      {
      return i1.method1() + i2.method2();
      }
   };

class C
   {
   int methodC(Interface2 &i2, Interface3 &i3)
      {
      return i2.method2() + i3.method3();
      }
   };

The caller can still choose to inherit from multiple interfaces, like this:

class MyClass : public Interface2, public Interface3
   {
   int method2() {...}
   int method3() {...}
   };
...
MyClass myClass;
C c;
c.methodC(myClass,myClass);
~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文