当前位置:天才代写 > tutorial > C语言/C++ 教程 > C++的可移植性和跨平台开拓[2]:语法

C++的可移植性和跨平台开拓[2]:语法

2017-11-03 08:00 星期五 所属: C语言/C++ 教程 浏览:333

副标题#e#

今朝尚有相当一部门开拓人员在利用老式编译器干活,这些老式编译器大概对C++98支持 不足。因此,当你的代码移植到这些老式的编译器上时,大概会遇到一些稀奇离奇的问题( 包罗编译堕落和运行时错误)。下面这些留意事项有助于你绕过这些问题。

强调一下 ,后头提到的好几个条款都是通过回避C++的新语法来担保移植性。假如你用的是新式编译器 ,那么你可以不剖析这些条款。

★小心for轮回变量的浸染域(不支持新尺度)

在C++98尺度中,for轮回变量的浸染域范围在轮回体内。而某些老的编译器(譬喻 Visual C++ 6)认为for轮回变量的浸染域在轮回体外。所以如下的代码大概导致移植问题。

{
 for(int i=0; i<XX; i++)
 {
  // ...
 }
 for(int i=0; i<XXX; i++)
 {
  // ...
 }
}

发起修改为差异的轮回变量,如下所示:

{
 for (int i=0; i<XX; i++)
 {
  // ...
 }
 for(int  j=0; j<XXX; j++)
 {
  // ...
 }
}

★不 要利用全局类工具,改用单键(尺度未界说)

全局类工具的结构函数先于main()函数 执行,假如某个模块中同时包括若干个全局类工具,则它们的结构函数的挪用顺序是不确定 的。而单键是在第一次挪用时被初始化,能制止此问题。别的,单键固然办理告终构问题, 可是析构依然有隐患。详见“C++ 工具是怎么死的?历程篇”。

★保持 inline函数只管简朴

不要在inline函数内部利用局部静态变量,不要在inline函数使 用可变参数。这些都有大概导致移植问题。

★不要依赖函数参数的求值顺序(尺度未 界说)

尺度没有明晰划定函数参数的求值顺序。因此,如下的代码行为是不确定的。

void Foo(int a, int b);
int n = 1;
foo(++n,  ++n);


#p#副标题#e#

★慎用模板特化(不支持新尺度)

有些老式编译器对偏特化或 全特化支持不足。

★模板担任中,引用基类成员要小心(不支持新尺度)

看 如下例子:

template <typename T>
class TBase
{
protected:
 typedef std::vector<T> Container;
 Container  m_container;
};
template <typename T>
class TDerived :  public TBase<T>
{
 typedef TBase<T> BaseClass;
public:
 void Func()
 {
  typename BaseClass::Container  foo;  //可移植
  Container foo; //不行移植
  this- >m_container.clear(); //可移植
  m_container.clear(); //不行移植
 }
};

★慎用RTTI(不支持新尺度、尺度未界说)

先声明一 下,我这里说的RTTI主要是指typeid操纵符和type_info范例。

首先,由于某些老式 编译器大概不支持typeid操纵符和type_info范例,会导致移植性的问题,这是慎用RTTI的一 个原因。(假如你用的是新式编译器,不消思量这个因素)

其次,由于尺度对付 type_info范例的约束较量简朴。这导致了差异的编译器对type_info的实现有较大差别。如 果你确实要利用type_info范例,发起仅仅利用它的operator==和operator!=这两个成员函数 。

所以,假如你确实需要在运行时确定范例,又不想遇到上述问题,可以思量在本身 的类体系中插手范例信息来实现。好比MFC和wxWidgets都是这么干的。

★慎用嵌套类 (不支持新尺度)

假如在内部类会见外部类的非公有成员,要把内部类声明为外部类 的friend。

如下代码存在移植问题。

class COuter
{
private:
 char* m_name;
public:
 class CInner
 {
  void Print(COuter* outer)
  {
   cout << outer- >m_name;
  }
 };
};

#p#副标题#e#

应该改为如下代码

class COuter
{
private:
 char* m_name;
public:
 class CInner; //前置声明
 friend class CInner;
  class CInner
 {
  void Print(COuter* outer)
  {
    cout << outer->m_name;
  }
 };
};

★ 不要界说参数范例临近的函数(尺度未界说)

void Foo(short n);
void Foo(long n);
Foo(0); //会导致二义性错误

★不要依赖标 准范例的字长(尺度未界说)

某些尺度范例(譬喻int、wchar_t)的字长会跟着详细 的平台而改变。

★用列举取代类的静态成员常量(不支持新尺度)

某些老式 的编译器不支持类的静态成员常量,可以用列举来取代。

class CFoo
{
 static const int MIN = 0; //不行移植
 enum { MAX = 64  }; //可移植
};

#p#分页标题#e#

本日说了这么一大堆,都较量琐碎,预计会有漏掉 的。日后假如大伙儿发明有增补的,接待在本帖的评论中指教一二。由于篇幅有限,我把和 异常相关的内容留到下一个话题。

原始地点:http://program- think.blogspot.com/

 

    关键字:

天才代写-代写联系方式