1 / 44

C++

C++. WindyWinter windy@ream.at. 课程适用性. 迫于时间所限,本课程只能面向 C 语言程序设计基础较好的 同学。 希望 经过短期训练, 让大家能 读 懂 WrightEagleBASE 中涉及语言特性的部分。 合格的 C++ 入门和参考书籍 有 C ++ Primer 、 The C++ Programming Language 和 Thinking in C ++ 。. C 语言复习. 整型. 浮点型. 浮点数也是离散的。

ula
Download Presentation

C++

An Image/Link below is provided (as is) to download presentation Download Policy: Content on the Website is provided to you AS IS for your information and personal use and may not be sold / licensed / shared on other websites without getting consent from its author. Content is provided to you AS IS for your information and personal use only. Download presentation by click this link. While downloading, if for some reason you are not able to download a presentation, the publisher may have deleted the file from their server. During download, if you can't get a presentation, the file might be deleted by the publisher.

E N D

Presentation Transcript


  1. C++ WindyWinter windy@ream.at

  2. 课程适用性 • 迫于时间所限,本课程只能面向C语言程序设计基础较好的同学。 • 希望经过短期训练,让大家能读懂WrightEagleBASE中涉及语言特性的部分。 • 合格的C++入门和参考书籍有C++ Primer、The C++ Programming Language和Thinking in C++。

  3. C语言复习

  4. 整型

  5. 浮点型 • 浮点数也是离散的。 • 浮点数的内部表示也是二进制,比如float,一共32个二进制位,所以不可能表示出超过2^32个数字。 • IEEE 754 • 浮点数的比较 • if (a == b) X • if (fabs(a-b) < FLT_EPSILON)O • if (fabs(a-b) < DBL_EPSILON) O

  6. 其它类型 • _Bool • float _Complex / double _Complex • 衍生类型 • array、structure、union、function、pointer • 类型限定符 • const、volitile、restricted • void类型 • 取值集合为空集的类型

  7. 其它类型 • bool • complex<float> / complex <double> • 衍生类型 • array、structure、union、function、pointer • 类型限定符 • const、volitile、restricted • void类型 • 取值集合为空集的类型

  8. 指针 • float * const float指针常量类型 • const float * 常量float类型的指针类型 • DecisionDataDerived** 指针的指针 • E1[E2]  (*((E1)+(E2))) • A[3]  *(A+3) • 3[A]  *(3+A) = *(A+3)

  9. const和#define • #define属于预编译的范围,“符号替换”;const定义的是“不能修改的”变量。 • #define只能定义有“字面值”的常量;const可以定义数组、结构体和union常量。 • enum可以定义整数常量,一般用于互相关联的一组整数。 • enumPlayMode{}

  10. 预编译指令 • #include 后面不是“字符串”,是用引号或者<>括起来的文件名。 • 条件编译 • #define 符号 • #undef符号 • #if / #elif字面值常量表达式 • #ifdef / #ifndef / #else 符号 • 不符合#if条件的代码段编译器不编译

  11. 预编译指令 • #define中“#”的用法 • #x 将x变成字符串 • x##y 将x与y连接起来 • #define TeammateFormationTactic(TacticName) (*(FormationTactic##TacticName *)mFormation.GetTeammateTactic(FTT_##TacticName)) • TeammateFormationTactic(KickOffPosition)  *(FormationTacticKickOffPosition*)mFormation.GetTeammateTactic(FTT_KickOffPosition))

  12. 其它 • sizeof运算符 • size_tfsize(int n) { char t[n+3]; return sizeof(t);}fsize(10) -> 13 • inline函数 • static变量

  13. C++标签

  14. 即时声明 • C语言要求所有变量的声明必须在实意语句之前,也就是在所有{}的外面,或者是每对{}的最前面。 • C++没有了这样的限制,变量只要遵循先声明后使用的原则就可以了,不再要求必须放在什么地方。我们可以在for语句头部塞上一个inti(0),for (inti(0); i < 10; ++i)。 • “inti(0)”里的(0)是指将i初始化为0,作用相当于inti=0。

  15. 引用 • 引用(reference)是C++新定义的一种复合类型,其本意可以理解为变量的“别名(alternate name)”。 • 声明/定义一个引用:int a;int & r = a; • r被定义为a的引用后,r和a可以被认为是同一个变量。 • 引用的主要用在函数形参中(作用与指针相仿): • 避免传递规模巨大的实参; • 将形参的值返回。

  16. 引用 • void BehaviorAttackPlanner::Plan(std::list<ActiveBehavior> & behavior_list) • PlayerState & player = const_cast<PlayerState &>(*mpWorldState->GetPlayerList()[i]);player.GetPos();

  17. 左值与右值

  18. 类型转换 • C++继承了原有的C语言的隐式类型转换; • 所有的类型都可以隐式转换为该类型的引用:int => int &,int * => int * &,所有的类型都可以隐式转换为该类型的常量; • 强制类型转换在C++中有了另一类写法: • (type) a  xxx_cast<type> a; • static_cast<type>实现与C中类型转换相同的功能; • const_cast<type>去掉表达式的常量性; • 另外还有reinterpret_cast和dynamic_cast

  19. 输入输出 • std::cout << a << b << c << d <<std::endl; • Logger::instance().GetTextLogger(“test”) << a << b << c << d << std::endl; • 输出到Logfiles/WrightEagle-X-test.log中。

  20. 形参默认值 • 形参允许有默认值,即函数可以声明为如下形式:boolKickBall( Agent & agent, double angle, double speed_out,KickModemode = KM_Hard,int*cycle_left = 0,boolis_shoot = false);

  21. 形参默认值 • 调用的时候可以不写有默认值的参数 • KickBall(agent, 0.0, 3.0); • KickBall(agent, 0.0, 3.0, KM_Quick); • KickBall(agent, 0.0, 3.0, KM_Quick, &cycle); • KickBall(agent, 0.0, 3.0, KM_Quick, &cycle, true); • 都是合法的 • 没写的参数,实参值就是默认值。

  22. 函数重载 • 允许不同的函数有相同的函数名。 • “不同的函数”是指形参的类型、数目或返回值的类型不同的函数。 • boolGoToPoint(Agent & agent, Vector pos, double buffer = 0.5, double power = 100.0, boolcan_inverse = true, boolturn_first = false); • void GoToPoint(Agent & agent, AtomicAction & act, Vector pos, double buffer = 0.5, double power = 100.0, boolcan_inverse = true, boolturn_first = false);

  23. new和delete运算符 • C语言用malloc和free。 • C++用new和delete。 • client = new Player; • delete client; • mWeight = new real**[mLayers]; • delete[] mWeight;

  24. 面向对象的C++

  25. • 类是C++的新特性,为适应面向对象的程序设计而提出; • 在C中,已经有了结构体的概念; • 类与结构体的最大不同之处在于——不仅可以包含成员变量(常量),还可以包含成员函数。 • 当然,类还包括一些其他的特性: • 成员变量、成员函数的访问权限; • 构造函数; • 析构函数; • 拷贝构造函数; • 隐式类型转换; • ……

  26. 一个著名的类 class BaseState { public: BaseState(); BaseState(constBaseState & o) {} void UpdatePos(const Vector & pos , int delay = 0, double conf = 1); const Vector & GetPos() const { return mPos.mValue; } intGetPosDelay() const { return mPos.mCycleDelay; } const double & GetPosConf() const { return mPos.mConf; } void UpdatePosEps(double eps) { mPosEps = eps;} const double & GetPosEps() const { return mPosEps;} private: StateValue<Vector> mPos; double mPosEps; };

  27. 成员函数的定义 • 成员函数可以直接在类定义里定义,也可以单独在外面定义。 • void BaseState::UpdatePos(const Vector & pos, int delay, double conf){mPos.mValue = pos;mPos.mCycleDelay = delay;mPos.mConf = conf;}

  28. this指针 • 每个类都有一个特殊的“成员”——this,表示对象自身; • this只能在该类的内部使用,与不指明this没有区别: • this->mPos mPos • this->mPosConf  mPosConf • void UpdatePosEps(double mPosEps) { this->mPosEps= mPosEps;}

  29. 成员函数的const属性 • constVector & GetPos() const • GetPos不能更改任何成员变量的值,在函数内部 • this指针变成指向常量的指针; • 任何成员变量被附加const属性。 • 这种声明主要用于指明该函数不会更改成员变量的值。

  30. 构造函数 • 没有返回值类型,与类同名的函数被认为是构造函数。BaseState() • 它的作用就是——构造一个对象。 • BaseState() : mPosEps(10000);{mPos.mValue= Vector(10000 , 10000);}

  31. 构造函数 • BaseState(const BaseState & o) { mPos = o.mPos;} • 如果将某个构造函数声明为private,则这个构造函数将无法使用。一般来说,这样做的目的是阻止编译器生成缺省的构造函数。 • class Agent{ Agent(Agent &); ……};

  32. 构造函数 • class Line {public: Line(constRay &r); ……}; • 只带有一个参数的构造函数表明了一种可能的隐式类型转换。

  33. 析构函数 • 没有返回值,名字是~<class name>,没有参数的函数是析构函数。构造函数可以有多个,析构函数只能有一个。 • 它的作用是销毁一个对象。 • 如果没有声明析构函数,编译器将合成默认析构函数 • 对于内置类型,释放其空间; • 对于类类型,调用其析构函数。 • 实际上,上面两步是编译器附加在任何析构函数最后的两步。因为没有办法显式“释放空间”和调用析构函数。

  34. new和delete运算符 • mallac/free和new/delete的区别在于 • 前者只涉及内存分配 • 后者不仅分配/释放空间,还要创建/销毁对象。 • new运算符首先分配对象占据的空间,然后在其上调用构造函数;delete首先完成对象本身的销毁步骤,然后释放空间。

  35. 静态成员 • static关键字也可以修饰类的成员 • class Dasher{public:static Dasher & instance();static Array<double, 8> DASH_DIR;static Array<int, 8> ANTI_DIR_IDX;static Array<double, 8> DIR_RATE;static intGetDashDirIdx(constAngleDeg & dir);}

  36. 静态成员 • 被修饰的成员叫做类的静态成员,是这个类的属性,不是某个对象的属性。 • 访问用:: • Dasher::instance() • Dasher::GetDashDirIdx()

  37. 运算符重载 • C++不仅提供了对函数的重载,也提供了对运算符的重载。运算符可以视为特殊的函数。 • 双目运算符 • Time Time::operator-(constinta); • int Time::operator-(const Time &a); • 单目运算符 • _Tp & ObjectArray::operator[](constObjectIndex & i) • 特别的运算符重载:++、--。

  38. 运算符重载 • 还有一类特殊的运算符也可以被重载: • opetator T()operator int();operator xxx(); • 这样的运算符必须是某个类的成员函数,它为这个类提供向特定类型的隐式类型转换。 • 更多的很多情况下,运算符重载是一个复杂的工程。在你真正掌握重载之前,请慎用。

  39. 继承与派生 class MobileState: public BaseState { void UpdateVel(const Vector & vel , int delay = 0, double conf = 1);const Vector & GetVel() const { return mVel.mValue; }intGetVelDelay() const { return mVel.mCycleDelay; } ……};

  40. 继承与派生 • 前面定义了BaseState类的一个派生类MobileState,BaseState是MobileState的基类。 • 它将获得BaseState类的一切成员,还另外附加了很多Vel相关的成员。 • “一切成员”,不包括基类的构造函数、析构函数、new运算符和=运算符。但派生类中可以访问他们。 • 派生类对象可以隐式转换为基类类型;派生类类型的指针可以隐式转换为基类类型的指针 • BaseState * object = new MobileState;

  41. 虚函数与多态 • 在声明某个成员函数时加上virtual修饰符,表示允许派生类重载该函数;在声明析构函数时加上virtual修饰符,产生特殊效果。 • class Client { virtual ~Client(); virtual void RunNormal(); ……};

  42. 虚函数与多态 • Client client= new Player;client->RunNormal(); • virtual void Run() = 0;

  43. 友元 • class Agent{ friend class Client; ……}; • 友元是一个声明。友元不是类的成员。

  44. Q&A

More Related