Inside the C++ Object Model 读书笔记(七)

本文介绍了C++中的模板概念及其在泛型编程中的应用。详细解释了模板声明、实例化的过程,以及成员函数如何按需实例化等内容。此外,还讨论了模板中错误报告、名称解析、成员函数实例化等关键问题。

Templates

Originally viewed as a support for container classes such as Lists and Arrays, templates are now the

  • generic programming (the Standard Template Library).
  • attribute mix-in where, for example, memory allocation strategies
  • mutual exclusion mechanisms for synchronizing threads ([SCHMIDT94])
  • a technique for template metaprograms

three primary aspects of template support:

  1. Processing of the template declarations
  2. Instantiation of the class object and inline nonmember and member template functions.
  3. Instantiation of the nonmember and member template functions and static template class members.

Template Instantiation

template <class Type> 
class Point 
{ 
public: 
   enum Status { unallocated, normalized }; 

   Point( Type x = 0.0, Type y = 0.0, Type z = 0.0 ); 
   ~Point(); 

   void* operator new( size_t ); 
   void  operator delete( void*, size_t ); 

   // ... 
private: 
   static Point< Type > *freeList; 
   static int chunkSize; 
   Type _x, _y, _z; 
}; 

when the compiler sees the template class declaration, do nothing. the static data members are not available. Nor is the nested enum or its enumerators.

If we define a pointer to a particular instance, such as

Point< float > *ptr = 0;

again, nothing happens in the program. Because a pointer to a class object is not itself a class object; the compiler does not need to know anything about the layout or members of the class.

const Point< float > &ref = 0; 

result in the instantiation of a float instance of Point, The actual semantics of this definition expand as follows:

// internal expansion 
Point< float > temporary( float (0) ); 
const Point< float > &ref = temporary; 

Member functions that are not used should not be instantiated. Standard C++ requires that member functions be instantiated only if they are used (current implementations do not strictly follow this requirement). There are two main reasons for the use-directed instantiation rule:

  • Space and time efficiency
  • Unimplemented functionality

Error Reporting within a Template

All type-dependent checking involving the template parameters must be deferred until an actual instantiation occurs.
In current implementation, that is, a template declaration has only limited error checking applied to it prior to an instantiation of an actual set of parameters.

Name Resolution within a Template

// scope of the template definition 

extern double foo ( double ); 

template < class type > 
class ScopeRules 
{ 
public: 
   void invariant() { 
      _member = foo( _val ); 
   } 

   type type_dependent() { 
      return foo( _member ); 
   } 
   // ... 
private: 
   int _val; 
   type _member; 
}; 

//scope of the template instantiation 

extern int foo( int ); 
// ... 
ScopeRules< int > sr0; 

The program site of the resolution of a nonmember name within a template is determined by whether the use of the name is dependent on the parameter types used to instantiate the template.

If the use is not dependent, then the scope of the template declaration determines the resolution of the name. If the use is dependent, then the scope of the template instantiation determines the resolution of the name.

This means an implementation must keep two scope contexts:

  • The scope of the template declaration, which is fixed to the generic template class representation
  • The scope of the template instantiation, which is fixed to the representation of the particular instance

The compiler’s resolution algorithm must determine which is the appropriate scope within which to search for the name.

Member Function Instantiation

Difficult aspect of template support is template function instantiation:

  1. How does the implementation find the function definition?
  2. How does the implementation instantiate only those member functions that are actually used by the application?
  3. How does the implementation prevent the instantiation of member definitions within multiple .o files?

the Standard has the following, otherwise puzzling clause in Section 14.3.2:

If a virtual function is instantiated, its point of instantiation is immediately following the point of instantiation for its class.

Exception Handling

The primary implementation task in supporting exception handling (EH): discover the appropriate catch clause to handle the thrown exception

Requirement:

  • implementation to somehow keep track of the active area of each function on the program stack (including keeping track of the local class objects active at that point in the function
  • must provide some method of querying the exception object as to its actual type (this leads directly to some form of runtime type identification (RTTI))
  • needs to be some mechanism for the management of the object thrown—its creation, storage, possible destruction

A Quick Review of Exception Handling

When an exception is thrown, control passes up the function call sequence until either an appropriate catch clause is matched or main() is reached without a handler’s being found, at which point the default handler, terminate(), is invoked

Exception Handling Support

When an exception is thrown, the compilation system must do the following:

  1. Examine the function in which the throw occurred.
  2. Determine if the throw occurred in a try block.
  3. If so, then the compilation system must compare the type of the exception against the type of each catch clause.
  4. If the types match, control must pass to the body of the catch clause.
  5. If either it is not within a try block or none of the catch clauses match, then the system must (a) destruct any active local objects, (b) unwind the current function from the stack, and © go to the next active function on the stack and repeat items 2–5.

Determine if the Throw Occurred within a try Block

A function, recall, can be thought of as a set of regions:

  • A region outside a try block with no active local objects
  • A region outside a try block but with one or more active local objects requiring destruction
  • A region within an active try block
catch( exPoint p ) 
{ 
   // do something 
   throw; 
} 

p is initialized by value with the exception object the same as if it were a formal argument of a function. This means a copy constructor and destructor, if defined or synthesized by the compiler, are applied to the local copy.

Because p is an object and not a reference, the non-exPoint portion of the exception object is sliced off when the values are copied. In addition, if virtual functions are provided for the exception hierarchy, the vptr of p is set to exPoint’s virtual table; the exception object’s vptr is not copied.

p is a local object destroyed at the close of the catch clause. Throwing p would require the generation of another temporary. It also would mean losing the exVertex portion of the original exception. The original exception object is rethrown; any modifications to p are discarded.

catch( exPoint &rp ) 
{ 
   // do something 
   throw; 
} 

refers to the actual exception object.

Any changes made to the exception object within a catch clause are local to the copy and are not reflected within errVer. The actual exception object is destroyed only after the evaluation of a catch clause that does not rethrow the exception.

Runtime Type Identification

The C++ RTTI mechanism provides a type-safe downcast facility but only for those types exhibiting polymorphism (those that make use of inheritance and dynamic binding).

References Are Not Pointers

  • If the reference is actually referring to the appropriate derived class or an object of a class subsequently derived from that class, the downcast is performed and the program may proceed.

  • If the reference is not actually a kind of the derived class, then because returning 0 is not viable, a bad_cast exception is thrown.

simplify_conv_op( const type &rt ) 
{ 
    try { 
      fct &rf = dynamic_cast< fct& >( rt ); 
      // ... 
    } 
    catch( bad_cast ) { 
      // ... mumble ... 
    } 
} 

The typeid operator returns a const reference of type type_info.

内容概要:本文介绍了一个基于MATLAB实现的无人机三维路径规划项目,采用蚁群算法(ACO)与多层感知机(MLP)相结合的混合模型(ACO-MLP)。该模型通过三维环境离散化建模,利用ACO进行全局路径搜索,并引入MLP对环境特征进行自适应学习与启发因子优化,实现路径的动态调整与多目标优化。项目解决了高维空间建模、动态障碍规避、局部最优陷阱、算法实时性及多目标权衡等关键技术难题,结合并行计算与参数自适应机制,提升了路径规划的智能性、安全性和工程适用性。文中提供了详细的模型架构、核心算法流程及MATLAB代码示例,涵盖空间建模、信息素更新、MLP训练与融合优化等关键步骤。; 适合人群:具备一定MATLAB编程基础,熟悉智能优化算法与神经网络的高校学生、科研人员及从事无人机路径规划相关工作的工程师;适合从事智能无人系统、自动驾驶、机器人导航等领域的研究人员; 使用场景及目标:①应用于复杂三维环境下的无人机路径规划,如城市物流、灾害救援、军事侦察等场景;②实现飞行安全、能耗优化、路径平滑与实时避障等多目标协同优化;③为智能无人系统的自主决策与环境适应能力提供算法支持; 阅读建议:此资源结合理论模型与MATLAB实践,建议读者在理解ACO与MLP基本原理的基础上,结合代码示例进行仿真调试,重点关注ACO-MLP融合机制、多目标优化函数设计及参数自适应策略的实现,以深入掌握混合智能算法在工程中的应用方法。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值