Warning: file_get_contents(/data/phpspider/zhask/data//catemap/8/design-patterns/2.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 A{ public: A(){ } ~A(){ } }; class AImpl : public A{ public: AImpl(){ a = new AInternal(); } AImpl(AInternal *a){ this->_a = a; }

考虑两类

class A{
     public:
       A(){
       }
       ~A(){
       }
};


class AImpl : public A{
      public:
         AImpl(){
             a = new AInternal();
         }
         AImpl(AInternal *a){
             this->_a = a;
         }
         ~AImpl(){
             if(a){
                delete a;
                a = null;
             }
         }
       private:
             AInternal *a;
};
我试图隐藏AInternal的实现,只公开A的接口。我在这里看到两件事

  • A班是空的
  • 隐藏基本上是通过继承实现的。实际上,我必须使用从A到AImpl的向下投射和向上投射,反之亦然

  • 这个设计好吗。由于在设计方面非常缺乏经验,我看不出它的缺陷以及为什么它不好?

    我认为这是没有道理的。无论你在那里做什么,都应该在AImpl中完成。否则,在C++中可以这样做。

    < p>代码相当钝,所以我担心在六个月内保持它。

    你使用3个类使事情变得过于复杂。我想你要找的是。

    如果你要这样做,那么析构函数
    ~A
    必须是
    虚拟的

    我试图隐藏AInternal的实现,只公开A的接口

    我想你是在尝试做类似的事情

    以下是一个例子:

     class IA {                                               
     public:
             IA() {}
             virtual ~IA() {}
             virtual void dosth() =0;
     };
    
     class Factory {
     private:
             class A : public IA {
             public:
                     A () {}
                     virtual ~A() {}
    
                     void dosth() { cout << "Hello World"; }
             };
    
     public:
             Factory () {}
             virtual ~Factory() {}
    
             IA*newA() { return new A; }
     };
    

    您似乎结合了两个常见的设计功能:

    1) 内部是一个“pimpl”。它提供了更好的封装,例如,如果需要向内部添加一个新字段,那么AImpl的大小不会改变。那很好

    2) 是用于指示接口的基类。既然您讨论了上转换和下转换,我假设您需要动态多态性,这意味着您将拥有传递指针或对的引用的函数,并且在运行时,referelands实际上是AImpl类型的。这也很好,除了A的析构函数应该是虚拟的和公共的,或者是非虚拟的和受保护的

    我认为这段代码没有其他设计问题。当然,您需要通过添加一些在AImpl中实现的纯虚拟成员函数来实际定义接口A。假设您计划这样做,那么使用空基类来实现在Java中由接口(如果您了解Java)提供服务的目的并没有错。通常,您会有一种工厂,它创建AImpl对象,并通过指针或对的引用返回它们(因此,向上转换它们)。如果客户机代码将直接创建AImpl对象,那么也可以,事实上,您可能根本不需要动态多态性。您可以改为进入模板


    我不明白的是,你为什么要沮丧(也就是说,对AImpl*投A*)。这通常是个坏消息。因此,您的设计中可能存在一些问题,只有通过向我们展示更多的类定义,以及实际使用A和AImpl的客户机代码,我们才能发现这些问题。

    可能是可编译的?所以用户只看到了一个,而它什么也不做?遗产有什么好处谷歌搜索“pimpl”(指向实现的指针)。请注意,
    if(a)
    检查析构函数是不必要的:首先,您可以删除空指针,其次,
    a
    在调用析构函数时将永远不会为空(
    new
    在失败时抛出异常)。+1。您可能希望为pImpl成员使用智能指针来增强异常安全性。我认为boost::scoped_ptr可能是理想的。cpp中的析构函数应该始终是虚拟的,而不仅仅是在这样的构造中。@qba:有三种不同用途的好选择:虚拟公共析构函数;非虚拟受保护析构函数;或者将该类记录为不用作具有动态多态性的基类。非常偶尔,为了特殊的技巧:私有析构函数+朋友。在本例中,该船可能使用了第三种选择。然而,在我看来,“你必须使你所有的析构函数都是虚拟的,因为我保留使用你的类进行动态多态性的权利,即使它不是为此而设计的”,这不是一个好的选择。我不同意。它不是一个真正的工厂,更像是一个包装器。我认为qba的要点是工厂可以通过返回一个抽象的基类指针来隐藏具体的类。这就是问题所要问的。这正是我所想的。
    Factory f;
    IA*a = f.newA();
    a->dosth();
    return 0;