C语言C++ - 邂逅对象

C的++

本文为那些年我们赶了的语言的C++篇。C语言的命名来源于其参考的B语言.
而C++的命名, 正因为所有C的思索和法则主导都被保存下来,
并且引入了看似的概念, 以及包装, 继承, 多态的思想. 关键是价值观的转变.
系统上, 推荐 C++
Primer

.

黑魔法

1. 模板 (Template)

虽说看似是C++与C最直观的分别方式, 但本文并无打算当其吃笔墨. 相较类,
多态的风味还吸引自己. 模板是一律种对项目进行参数化的家伙, 通常有星星点点种样式:
针对参数类型不同之函数模板, 以及针对属性与操作类型不同的类模板.
使用模板可以为类或函数声明构造一种通用模式,
使类似中一些成员或函数的参数与返回值类型任意。深入上要阅读 C++
Templates

.

2. 专业模板库 (STL)

STL (Standard Template Library) 的核心部件包括: 容器 (Container), 算法
(Algorithms), 迭代器 (Iterator). 简单的话, 它们分别表示结构, 操作, 指针.
STL的一个着重特征是她不是面向对象的. 它根据模板而不是OOP中之包, 继承,
多态. 关于STL的情节请参考学习:

  • Standard_Template_Library
  • STL
    Reference
  • STL’s
    Guide
  • STL源码剖析

每当C++ STL中, 很多局部 (set, multiset, map, multimap)
应用了红黑树的变体.
红黑树操作有良好的极度深情况复杂度, 在实践中, 它可展开O(log
n)光阴外之探寻,插入和去等操作.
红黑树是每个节点都富含红色或黑色的二叉平衡查找树.
具有如下性质:

  1. 节点是革命或黑色.
  2. 穷节点是黑色.
  3. 每个叶节点 (NIL节点) 是黑色.
  4. 每个红节点的个别单子节点都是黑色,
    从每个叶子到干净的保有路线上无克起半点单连续的革命节点.
  5. 自无一省点交该每个叶子的备途径都含相同数量的黑色节点.

这些性确定了红黑树的关键性能:
从根本及叶子的极度丰富或者路径不多于最短可能路径的有限倍长.
其利是既保持了培训之对立平衡, 又比AVL的插删除操作的错综复杂低许多.
红黑树的插及删除操作会破坏性质, 因此要经旋转来维护.
直观了解保护操作请圈红黑树从头至尾插入和去结点的全程演示图.
该文作者所描写的开门红黑树专题挺确切,
值得研读.

3. 回调 (Callback)

重精确的说, 回调是C的性质.
首次等沾回调函数是于ns-3遭逢,
其作用是深受某函数以函数指针的样式变为有类的性能,
以供应该类在适用的早晚调用该函数.
引用ns-3的Tutorial蒙之讲授:

The goal of the Callback system in ns-3 is to allow one piece of code
to call a function (or method in C++) without any specific
inter-module dependency. This ultimately means you need some kind of
indirection – you treat the address of the called function as a
variable. This variable is called a pointer-to-function variable.

举个ns-3中碰到的有关wifi中mac层收包的例子, 为保证原汁原味,
代码中部分及回调无关的始末无去:

class MacRxMiddle{
  typedef Callback<void, Ptr<Packet>, const WifiMacHeader*> ForwardUpCallback;
  ForwardUpCallback m_callback;
  void SetForwardCallback (ForwardUpCallback callback);
  void Receive (Ptr<Packet> packet, const WifiMacHeader *hdr);
  ...
};

void MacRxMiddle::SetForwardCallback (ForwardUpCallback callback){
  m_callback = callback;
}

void MacRxMiddle::Receive (Ptr<Packet> packet, const WifiMacHeader *hdr){
  NS_LOG_FUNCTION (packet << hdr);
  NS_ASSERT (hdr->IsData () || hdr->IsMgt ());
  OriginatorRxStatus *originator = Lookup (hdr);
  if (!(SequenceNumber16 (originator->GetLastSequenceControl ()) < SequenceNumber16 (hdr->GetSequenceControl ()))) NS_LOG_DEBUG ("Sequence numbers have looped back. last recorded=" << originator->GetLastSequenceControl () << " currently seen=" << hdr->GetSequenceControl ());
  if(IsDuplicate (hdr, originator))
    NS_LOG_DEBUG ("duplicate from=" << hdr->GetAddr2 () <<", seq=" << hdr->GetSequenceNumber () <<", frag=" << hdr->GetFragmentNumber ());
    return;
  }
  Ptr<Packet> agregate = HandleFragments (packet, hdr, originator);
  if (agregate == 0) return 0;
  if (!hdr->GetAddr1 ().IsGroup ()) originator->SetSequenceControl (hdr->GetSequenceControl ());
  m_callback (agregate, hdr);
}

/////////////////////////////////////////////////////////////////////////////////////////////////////////////////
class RegularWifiMac : public WifiMac{
  RegularWifiMac ();
  virtual void Receive (Ptr<Packet> packet, const WifiMacHeader *hdr);
  MacRxMiddle *m_rxMiddle;
  ...
};

RegularWifiMac::RegularWifiMac (){
  m_rxMiddle->SetForwardCallback (MakeCallback (&RegularWifiMac::Receive, this));
  ...
}

void RegularWifiMac::Receive (Ptr<Packet> packet, const WifiMacHeader *hdr){
  NS_LOG_FUNCTION (this << packet << hdr);
  Mac48Address to = hdr->GetAddr1 ();
  Mac48Address from = hdr->GetAddr2 ();
  if (to != GetAddress ()) return;
  if (hdr->IsMgt () && hdr->IsAction ()){
    NS_ASSERT (m_qosSupported);
    WifiActionHeader actionHdr;
    packet->RemoveHeader (actionHdr);
    switch (actionHdr.GetCategory ()){
      case WifiActionHeader::BLOCK_ACK:
        ...
      default:
        NS_FATAL_ERROR ("Unsupported Action frame received");
        return;
      }
   }
  NS_FATAL_ERROR ("Don't know how to handle frame (type=" << hdr->GetType ());
}

随即段代码中含有两只类MacRxMiddle和RegularWifiMac. 首先,
MacRxMiddle中起一个回调变量ForwardUpCallback m_callback;,
同时有两只操作, 用于设置m_callback的SetForwardCallback函数,
及用于拍卖收包行为的操作Receive函数. 并且,
Receive函数最后之话语m_callback (agregate, hdr);,
是一个调用回调函数的语句. 然后, 分析类RegularWifiMac,
它蕴含一个MacRxMiddle类的实例化指针MacRxMiddle *m_rxMiddle;. 并且,
在初始化时,
通过m_rxMiddle->SetForwardCallback (MakeCallback (&RegularWifiMac::Receive, this));用RegularWifiMac::Receive函数关联刚刚提到的MacRxMiddle中之m_callback.
简单的话, 以上程序用回调达到效果是,
MacRxMiddle::Receive中之m_callback (agregate, hdr);可以轮换为RegularWifiMac::Receive (agregate, hdr);.
那么, 到底为什么要采用回调函数,
而未是一直当MacRxMiddle中编RegularWifiMac::Receive函数呢?
因为RegularWifiMac类需要之凡RegularWifiMac::Receive行为,
但是其它类似吃的MacRxMiddle实例, 需要之也许就是是另外收包行为.
这就是是回调的魅力.

结束语

虽new过那么基本上只object, 然而就并没有啊…

C++