为什么Google不希望您使用C ++构造函数?

时间:2014-02-27 21:41:58

标签: c++ v8

     /**
     * A JavaScript value representing a signed integer.
     */
    class V8_EXPORT Integer : public Number {
     public:
      static Local<Integer> New(Isolate* isolate, int32_t value);
      static Local<Integer> NewFromUnsigned(Isolate* isolate, uint32_t value);
      int64_t Value() const;
      V8_INLINE static Integer* Cast(v8::Value* obj);
     private:
      Integer();
      static void CheckCast(v8::Value* obj);
    };

以上代码来自Google的V8引擎。初始化示例如下:

Handle<Value> x = Integer::New(42);

从我在源代码中看到的,他们将构造函数标记为私有,并希望您使用New函数来创建此类的实例。这不符合标准的C ++设计模式吗?为什么他们只是重载构造函数而不是创建静态函数?这通常是当人们试图将一个库从一种语言移植到另一种语言时你看到的那种东西(我现在唯一可以想到的就是Xamarin的iOS工具包)。

我试图谷歌周围的这个类型的公约的名称,但无法真正找到任何东西。

4 个答案:

答案 0 :(得分:3)

这是一种名为“静态工厂方法”的模式,由Joshua Bloch推荐为“Effective Java”中的第1项。 (我几乎可以肯定Scott Myers在“Effective C ++”中有一个等效的项目,但是现在我没有这本书的副本可供检查。)

通过这种方法创建对象的优势,而不是普通的构造函数,由Bloch描述为:

  
      
  • 此类方法可能具有描述性名称
  •   
  • 与构造函数不同,这些方法不需要创建一个全新的对象,即它们可以返回先前缓存的副本   对象。
  •   
  • 与构造函数不同,此类方法还可以返回其返回类型
  • 的任何子类型的对象   
  • 此类方法可降低参数化对象构造的详细程度
  •   

这种设计模式也存在缺点,在某些情况下只是建议。

可能在V8的情况下,列表中的第二点是最重要的,以加快构造。我不是V8专家,但似乎“事件驱动,单线程”是它的理念。当许多“事件回调”想要拥有一个相同的数字时,所有这些都得到该数字的同一个实例的副本。

答案 1 :(得分:2)

手柄有两种类型。其中一个是“本地”句柄。如代码所示,本地句柄具有类Handle<SomeType>

https://developers.google.com/v8/embed

  

注意:句柄堆栈不是C ++调用堆栈的一部分,而是   句柄范围嵌入在C ++堆栈中。处理范围只能是   堆栈分配,未分配新的。

https://developers.google.com/v8/get_started

  
      
  • 句柄是指向对象的指针。使用句柄访问所有V8对象,由于V8垃圾的方式,它们是必需的   收藏家的作品。
  •   

答案 2 :(得分:1)

看起来他们正在使用静态工厂方法。当您想要集中创建对象时,这是有意义的,因为它必须以特殊方式完成。我可以想象构造函数提供了一个普通的有效整数对象,并且工厂方法比调用其他方法使对象进入特殊的初始状态。

将构造函数限制为尽可能小是一个好主意。构造函数应该建立类的不变量。然后可以通过特殊方法完成其他设置,并且可以在工厂中封装特定初始化对象的创建。

答案 3 :(得分:1)

使用工厂方法从低级C ++构造函数中抽象出来的最重要原因是需要在此API中组合分配和构造。大多数工厂方法执行分配。但是,这种分配必须发生在(垃圾收集的)JavaScript堆上,而不是C ++堆上。这有几个后果:

  1. 我们不允许在没有分配的情况下构造原始对象,例如在堆栈上。

  2. 我们不能允许使用C ++ - new

  3. 默认情况下我们不能允许使用原始指针,因为这会破坏垃圾收集(句柄是GC知道的间接并且可以更新以进行重定位)。

  4. 工厂方法有助于实施这些限制。