C++ 的 idioms(十四)

nullptr

C++11 引入的新特性。主要出现的问题是如果重载函数支持指针和整数两种,那么传入 NULL 就会表意不准确,有的定义为 0 有的定义为 (void*) 0,这就会引起问题。为此 C++11 引入了所谓 nullptr,这个也可以用一些现在 C++ 的语法获得类似的效果。

const // It is a const object...
class nullptr_t
{
  public:
    template<class T>
    inline operator T*() const // convertible to any type of null non-member pointer...
    { return 0; }

    template<class C, class T>
    inline operator T C::*() const   // or any type of null member pointer...
    { return 0; }

  private:
    void operator&() const;  // Can't take address of nullptr

} nullptr = {};

object generator

这个是比较常见的技术了,写了一堆 template class,一般会写个 helper function,用来生成这些 object。STL 的 functional 里面有不少类似东西。

parametrized base class

这个想法一般是将某些 interface 绑定到任意类上去的方案,同时也可以和 policy 这种静态的东西一起用。

template <class T>
class serializable : public T, public iserizable {
  virtual void serialize () {
    // implementation
  }
} ;

policy clone

这个技术也称为是 template parameter rebind,在编译器不支持 template-template parameter 的时候可以用来达到类似的效果。

template <class T>
struct allocator {
  template <class U> struct rebind {
    typedef allocator<U> other ;
  } ;
  // more ...
} ;

template <class T, class Alloc = allocator<T> >
struct list {
  struct list_node {T data ; list_node* next ;} ;
  typedef typename Alloc::rebind<list_node>::other allocator ;
} ;

polymorphic exception

有人说 singleton 与 exception 是两个违背软件工程基本原则 DIP(dependency inversion principle)的例子,DIP 的意思是说软件设计要通过“接口”消除对特定实现的依赖,而 singleton 使用的时候需要直接使用类名调用 static 方法获得实例,exception 在抛出的时候也是写具体的 exception 类名的。事实上 exception 也可以构造自己的 hierarchy,并在具体实现时具有不同的行为。下面是 wikibooks 给出的例子。

struct ExceptionBase  {
  virtual void raise() { throw *this; }
  virtual ~ExceptionBase() {}
};
struct ExceptionDerived : ExceptionBase {
  virtual void raise() { throw *this; }
};
void foo(ExceptionBase& e) {
   e.raise();
}

这似乎意味着必须将 exception 对象当做参数传递。个人感觉是不是 STL 里面那种通过不同类型区分不同类型的 exception 更好一些。似乎没必要让 exception 具有这种动态多态性。

Resource Acquisition is Initialization

这句话常被缩写为 RAII,很重要的就是通过对象的构造函数和析构函数对确保资源的正确获得和释放,特别中间存在异常的时候,C++ 保证对象的释放,所以比如分配内存或者加锁等操作的逆过程通过如此封装后就能保证即便有异常抛出也能够释放内存和解锁。对此有不少例子,如 std::auto_ptr、boost::scoped_ptr 和 boost::mutex::scoped_lock。

resource return

所谓的 resource return 就是指某些函数需要返回资源的时候的方式,比较常见的就是 std::auto_ptr 之类的对指针进行封装。这样保证就算调用者没有释放或者处理,资源也能被释放而不是泄露。

return type resolver

如果写个模板类,返回一个复杂的类型,写出来的 code 就会比较冗余…

template <class T> struct job {
  T get () {
    // ...
    return T (...) ;
  }
} ;

something_complicated a = job<something_complicated>.get () ;

咋省掉一个呢?

template <class T> struct job {
  operator T () {
    // ...
    return T (...) ;
  }
} ;

利用 conversion operator 搞定。wikibooks 里面的例子是将 template 写到 conversion operator,如果需要的话。

——————
And he said to him, Take me an heifer of three years old, and a she goat of three years old, and a ram of three years old, and a turtledove, and a young pigeon.

Advertisements
C++ 的 idioms(十四)

发表评论

Fill in your details below or click an icon to log in:

WordPress.com Logo

You are commenting using your WordPress.com account. Log Out / 更改 )

Twitter picture

You are commenting using your Twitter account. Log Out / 更改 )

Facebook photo

You are commenting using your Facebook account. Log Out / 更改 )

Google+ photo

You are commenting using your Google+ account. Log Out / 更改 )

Connecting to %s