Warning: file_get_contents(/data/phpspider/zhask/data//catemap/6/cplusplus/152.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
C++ 类与不同所有者的兼容性_C++_Design Patterns - Fatal编程技术网

C++ 类与不同所有者的兼容性

C++ 类与不同所有者的兼容性,c++,design-patterns,C++,Design Patterns,给定的: class Foo1 { public: typedef Foo2 owner; }; class Foo2 { public: typedef Foo1 vassal; typedef Foo3 owner; }; //... and so on class FooN { public: typedef FooNm1 vassal; typedef ExternalType owner; // problem owner* owner(); };

给定的

class Foo1 { 
 public:
  typedef Foo2 owner;
};
class Foo2 {
 public:
  typedef Foo1 vassal;
  typedef Foo3 owner;
};
//... and so on 
class FooN {
 public:
  typedef FooNm1 vassal;
  typedef ExternalType owner;  // problem
  owner* owner();
};
问题:

如何将类层次结构与外部所有者关联,保持不同所有者的类之间的兼容性

问题

  • 如果我们将FooN作为一个模板,并将owner作为模板参数,那么Foo{N}层次结构的每个类都将通过依赖链被该所有者感染
  • 如果我们为外部所有者创建一个接口FooNOwner以从中继承,那么我们就需要动态转换,从Foo{N}层次结构上的算法转移到实际所有者
  • 有没有一种设计模式可以解决我的问题

    出现这些问题的情况示例: 您有一个由Foo{N}类组成的结构。它用于快速搜索,其中的查询返回Foo{N}对象列表。我想从返回的FooN对象中获取一个具体类型ExternalOwner*的指向外部所有者的指针,从而避免动态强制转换。同时,我希望使用具有不同FooN::owner的Foo{N}(可能没有FooN)对象进行操作,而不必回顾这种差异

    更新:

    也许唯一有效的方法是定义公共所有者接口,并由所有者重载它,以便在发生不同所有者类的上下文中使用。因此,该接口由其使用上下文定义(但FooN与FooN::owner使用上下文无关)。这就是我最初试图解决的问题——将不同的任务分开,这种方法对我没有帮助

    我的解决方案


    我以双重派遣而告终。如果我添加虚拟void apply(FooOwnerVisitor*)=0;函数添加到FooOwner,并在附近定义FooOwnerVisitor接口,然后我可以为FooOwner派生添加任何功能,而不会影响FooN层次结构和动态转换。

    我认为没有人清楚您的需求,但这是我解决此问题的最佳猜测。。。演示如何在模板解决方案中处理所谓的“依赖链”。如果这没有帮助,但有任何关联,那么解释它和问题将有助于人们帮助你。如果您想在
    Foo
    对象上应用算法循环,我可以说明如何做到这一点

    #include <iostream>
    
    struct Abstract_Bar
    {
        virtual void f() const = 0;
    };
    
    struct Bar1 : Abstract_Bar
    {
        void f() const { std::cout << "Bar1\n"; }
    };
    
    struct Bar2 : Abstract_Bar
    {
        void f() const { std::cout << "Bar2\n"; }
    };
    
    template <int N>
    struct Foo
    {
        typedef Foo<N - 1> Lower;
        typedef Foo<N + 1> Higher;
    
        void f() const { std::cout << "Foo<N>\n"; }
    
        Higher* higher_;
    };
    
    template <>
    struct Foo<1>
    {
        typedef Foo<2> Higher;
    
        void f() const { std::cout << "Foo<1>\n"; }
    
        Higher* higher_;
    };
    
    template <>
    struct Foo<4>
    {
        typedef Foo<3> Lower;
        typedef Abstract_Bar Higher;
    
        void f() const { std::cout << "Foo<4>\n"; }
    
        Higher* higher_;
    };
    
    int main()
    {
        Foo<1> foo1;
        Foo<2> foo2;
        Foo<3> foo3;
        Foo<4> foo4;
        foo1.higher_ = &foo2;
        foo2.higher_ = &foo3;
        foo3.higher_ = &foo4;
        Bar1 bar1;
        foo4.higher_ = &bar1;
    
        foo1.f();
        foo2.f();
        foo3.f();
        foo4.f();
    
        foo1.higher_->f();
        foo2.higher_->f();
        foo3.higher_->f();
        foo4.higher_->f();
    
        // switch to another type of "Bar"...
        Bar2 bar2;
        foo4.higher_ = &bar2;
        foo4.higher_->f();
    }
    
    #包括
    结构抽象工具栏
    {
    虚空f()常数=0;
    };
    结构条1:抽象条
    {
    void f()常量{std::cout f();
    foo3.更高的_uf->f();
    foo4.更高的_uf->f();
    //切换到另一种类型的“酒吧”。。。
    Bar2-Bar2;
    foo4.higher=&bar2;
    foo4.更高的_uf->f();
    }
    
    我以双重分派结束。如果我添加虚拟void apply(FooOwnerVisitor*)=0;函数到FooOwner并在附近定义FooOwnerVisitor接口,然后我可以为FooOwner派生添加任何功能,而不会影响FooN层次结构,也不会动态转换。因此,我的问题实际上是两个有自己解决方案的问题。首先-如何使来自不同所有者的FooN类兼容-从所有者接口继承。第二,如何避免FooOut所有者派生类的动态转换——使用访问者模式。必须考虑将问题分成更小的并结合原子解决方案。

    我不理解你的第二个问题。你能给出一个你想要应用什么样的算法的例子吗?1。你希望得到什么?2。问题是什么?确切地说,这个问题存在着随意的泛化和不必要的模糊性。发布您的实际代码。或者至少是一个编译的具体示例。“结构由FooN类组成”-您是指
    struct{foo1f1;foo2f2;…};
    还是以某种方式存储任何Foo{N}对象的数据结构(例如boost variant/any),可能与“query…return list of FooN”,否则会引发问题“什么样的列表?”它们是不同的类型,没有公共基,不能有它们的std::list。P1:true。也许可以使用虚拟函数而不是动态强制转换?或者
    模板void f(Any_Foo&f){vassal v;…}
    ?@Space\u C0wb0y,@Alexander,@Alf我已经添加了示例,请参见。我的问题是如何实现FooN::owner以了解实际的外部所有者类,但不感染Foo{N}学习这些知识。也许一个解决方法是将动态强制转换封装到FooN::owner界面中…@Riga:不客气……我仍然不确定它有多重要,但会留意您的进一步反馈。干杯。@Tony,为了说明我在使用您的设计栏时遇到的问题,我在Foo中预定义了更高的值。1)我需要能够rk具有各种类型的Foo::Higher.2),并且能够将具有Higher::Higher Bar1和Higher::Higher Bar2的对象作为一种类型的对象来操作。@Riga:对于上面的1),您将使用各种“Bar”“在运行时?因此,您必须说Bar1和Bar2,并且需要Foo指向任一类型的对象,但要能够以某种方式对其进行操作(对于2),要指向具有Bar1/Bar2”作为一种类型对象的运算符”是多态性:使用编译时多态性——重载、模板化函数或运行时多态性——如果您从指定公用API的抽象基派生BAR1和BAR2,语言提供虚拟函数,或者您可以考虑ALLA Boost变体,任何或RTTI/DyrimCype如您所说的。@里加:我已经更新了代码AB。ove演示Bar1或Bar2对象的运行时选择。@Tony,我们现在正处于讨论的切入点。我不想使用dynamic_cast,我希望Foo具有函数get_higher()它返回的不是AbstractBar*,而是Bar1*或Bar2*。我的建议是可以开发一些结构FooOwner来实现这一点:Foo::Higher是FooOwner,但FooOwner可以反过来拥有抽象虚拟函数get()可以重载以返回派生的Bar1。为此,FooOwner可以在Bar1使用方面而不是在完成模板上重载,因为返回类型不是函数签名的一部分,可以在实现中更改。