C++ Idioms 03

  • 本文介绍了 C++ 的 5 个特别用法(Idioms),分别是
    • Curiously Recurring Template Pattern;
    • Empty Base Optimization;
    • Erase-Remove;
    • Inner Class;
    • Int to Type;

11. Curiously Recurring Template Pattern

用途

  • 使用派生类作为模板参数特化基类模板
  • 静态多态
  • 对象计数器

示例代码

静态多态

template <typename D>
class Base
{
public:
  void interface() {
    cout << "void Base::interface(), begin..." << endl;
    static_cast<D*>(this)->implementation();
    cout << "void Base::interface(), end..." << endl;
  }

  static void static_interface() {
    cout << "static void Base::static_interface(), begin..." << endl;
    D::static_implementation();
    cout << "static void Base::static_interface(), end..." << endl;
  }

  void implementation() {
    cout << "void Base::implementation(), begin..." << endl;
    cout << "void Base::implementation(), end..." << endl;
  }

  static void static_implementation() {
    cout << "static void Base::static_implementation(), begin..." << endl;
    cout << "static void Base::static_implementation(), end..." << endl;
  }
};

class Derived : public Base<Derived>
{
public:
  static void static_implementation() {
    cout << "static void Derived::static_implementation(), begin..." << endl;
    cout << "static void Derived::static_implementation(), end..." << endl;
  }

  void implementation() {
    cout << "void Derived::implementation(), begin..." << endl;
    cout << "void Derived::implementation(), end..." << endl;
  }
};

int main() {
  Derived::static_implementation();
  Derived::static_interface();
  Base<Derived>::static_implementation();
  Base<Derived>::static_interface();
  Base<Derived> bd;
  bd.implementation();
  bd.interface();
  bd.static_implementation();
  bd.static_interface();
  return 0;
}

对象计数器

template <typename T>
class Counter
{
public:
  static size_t objects_created;
  static size_t objects_alive;

public:
  Counter() { ++objects_created; ++objects_alive; }
  Counter(const Counter& c) { ++objects_created; ++objects_alive; }

protected:
  ~Counter() { --objects_alive; }
};

template <typename T>
size_t Counter<T>::objects_created;

template <typename T>
size_t Counter<T>::objects_alive;

class Point : public Counter<Point>
{
public:
  Point() : x(0.0), y(0.0), z(0.0) {}
  Point(double xx, double yy, double zz) : x(xx), y(yy), z(zz) {}
  Point(const Point& p) : x(p.x), y(p.y), z(p.z) {}
private:
  double x, y, z;
};

void count_point() {
  cout << "There are " << Counter<Point>::objects_created << " points created." << endl;
  cout << "There are " << Counter<Point>::objects_alive << " points still alive." << endl;
}

int main() {
  Point p1;
  count_point();
  Point p2, p3 = p1;
  count_point();
  {
    Point p4;
    count_point();
    Point p5;
  }
  count_point();
  return 0;
}

12. Empty Base Optimization

用途

  • 空类的对象的大小不能为 0,否则如下代码所示数组将无法正常工作
class Empty {};
Empty arr[10];      // 10 个空类对象,如果每个对象的大小为 0,则对象之间无法区分
Empty* p = arr + 1; // 指针运算在空类对象为 0 时也无法正常工作
  • 但是当空类对象是另一个类的数据成员时,却因为字节对齐造成空间浪费
  • C++ 的做法是
    • 空类的大小为 1
    • 如果一个类继承自空类,则该类不会将这 1 个字节包含在内
    • 如果一个类有空类对象成员,还是会保留这个字节,并执行对齐

示例代码

class E1 {}; 
class E2 {}; 

template <class Base1, class Base2, class Member> 
struct BaseOptimization// : private Base1, private Base2 
{ 
    Member member; 
    BaseOptimization() {} 
    BaseOptimization(const Base1& b1, const Base2& b2, const Member& mem) 
        : Base1(b1), Base2(b2), member(mem) {} 
};

class Foo 
{ 
  BaseOptimization<E1, E2, int> data; 
}; 

int main() {
  cout << "size of BaseOptimization: " << sizeof(BaseOptimization<E1, E2, int>) << endl;  // 4
  cout << "size of Foo: " << sizeof(Foo) << endl;                                         // 4
  return 0;
}

13. Erase-Remove

用途

  • 正确地真正删除容器中的元素

示例代码

template <typename T>
inline void remove_all_items(std::vector<T>& v, const T& item) {
  v.erase(std::remove(v.begin(), v.end(), item), v.end());
}

template <typename C>
inline void print_container(const C& c) {
  for (auto it = c.begin(); it != c.end(); ++it)
    cout << *it << " ";
  cout << endl;
}

int main() {
  vector<int> int_vec{0, 1, 1, 2, 4, 6, 6, 8};
  print_container(int_vec);
  cout << int_vec.size() << endl;   // 8
  remove_all_items(int_vec, 6);
  print_container(int_vec);
  cout << int_vec.size() << endl;   // 6
  return 0;
}

14. Inner Class

用途

  • 在不使用多重继承的情况下实现多组接口
  • 在一个抽象内提供一个接口的多种实现

示例代码

class Base1
{
public:
  virtual void func() = 0;
  ~Base1() {} // 非虚函数
};

class Base2
{
public:
  virtual void func() = 0;
  ~Base2() {} // 非虚函数
};

class Derived
{
  friend class Base1Impl;
  friend class Base2Impl;

private:
  class Base1Impl : public Base1
  {
  public:
    Base1Impl(Derived* pd) : parent(pd) {}
    void func() override { return parent->base1_func(); }
  private:
    Derived* parent;
  } base1_obj;

  class Base2Impl : public Base2
  {
  public:
    Base2Impl(Derived* pd) : parent(pd) {}
    void func() override { return parent->base2_func(); }
  private:
    Derived* parent;
  } base2_obj;

  void base1_func() { cout << "Derived::base1_func()" << endl; }
  void base2_func() { cout << "Derived::base2_func()" << endl; }

public:
  Derived() : base1_obj(this), base2_obj(this) {}

  operator Base1&() { return base1_obj; }
  operator Base2&() { return base2_obj; }
};

void base1_func(Base1& b1) { return b1.func(); }
void base2_func(Base2& b2) { return b2.func(); }


int main() {
  Derived d;
  base1_func(d);
  base2_func(d);
  return 0;
}

15. Int to Type

用途

  • 一个整数代表一个不同的类
  • 函数重载:根据不同的整数调用不同的函数

示例代码

template <int I>
struct Int2Type       // Int2Type<0>, Int2Type<0>, Int2Type<0>... 都是不同的类型
{
  enum {value = I};
  using value_type = int;
  using type = Int2Type<I>;
  using next = Int2Type<I + 1>;
  using previous = Int2Type<I - 1>;
};

template <typename T, size_t N>
class Array : public array<T, N>
{
private:
  enum AlgorithmType {NOOP, INSERTION_SORT, QUICK_SORT};
  static const int algo = (N == 0) ? NOOP :
                          (N == 1) ? NOOP :
                          (N < 50) ? INSERTION_SORT : QUICK_SORT;

  void sort(Int2Type<NOOP>) { cout << "sort: NOOP" << endl; }
  void sort(Int2Type<INSERTION_SORT>) { cout << "sort: INSERTION_SORT" << endl; }
  void sort(Int2Type<QUICK_SORT>) { cout << "sort: QUICK_SORT" << endl; }

public:
  void sort() { sort(Int2Type<algo>()); }   // 注意传入的是由 Int2Type<algo> 构造的对象
};

int main() {
  Array<int, 1> arr1;
  arr1.sort();
  Array<int, 10> arr10;
  arr10.sort();
  Array<int, 100> arr100;
  arr100.sort();
  return 0;
}
  • 0
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值