C++ 高阶基础

指针 和 函数 (By Jabin)

  • C++ Primer Plus 中文 第六版
  • Essential C++ 中文版
  • 深度探索 C++ 对象模型
  • C++ 程序设计语言(1-3)(4) 第四版 英文版
  • A Tour of C++ (Second Edition)
  • Professional C++ (4th Edition)
  • 指针

    int* p; int* 是一个指针类型 定义了一个int* 类型的指针

    int *p; *p是一个int类型的值

    int n = 4;
    int *p = &n
    

    声明语句中初始化指针,被初始化的是指针,而不是指向它的值。

    c++中创建指针,计算机将分配用来存储地址的内存,不会分配用来存储指针所指向的数据的内存***

  • * 与 ++

    前缀递增(++)、递减(--)与 * 优先级相同,以从右到左的方式进行结合
    后缀递增、递减优先级相同,但比前缀递增、递减的优先级高,以从左往右的方式结合

    double arr[5] = {1.1, 2.2, 3.3, 4.4, 5.5};
    double *ptr = arr;
    ++ptr; //point to arr[1]
    *++ptr; //先++后*取值 即指针指向arr[1],再取arr[1]的值,最后ptr指向不变 结果为2.2
    ++*ptr; //先取arr[0]的值,再对值进行++操作,最后ptr指向不变,结果为1.1 + 1 = 2.1
    (*ptr)++; //带括号优先级高,先取arr[1]的值,再进行++操作,++后置所以结果为 1.1,指针*ptr指向2.1
    *ptr++; //先ptr++,再取值,同样因为++后置所以结果为1.1,指针*ptr位置+1,指向2.2
    
    
  • 函数转换

    class Page{
    public:
        Page();
        Page(int n); //前面加explicit 禁止隐式转换
        operator int() const;
    }
    
    //usage:
    Page page(10);  //int to Page
    or 
    Page page;
    page = 10;
    
    int n = page; // n = 10;
    
  • 返回对象

    Test GetOne(const Test & t1, const Test t2)
    {
      if(true) return t1;
      return t2;
    }
    
    const Test & GetOne(const Test & t1, const Test & t2)
    {
        if(true) return t1;
        return t2;
    }
    
    //Note:
    //1. 返回对象会调用复制构造函数,返回引用不会,第二个效率高
    //2. 引用指向的对象应该在调用函数执行时存在
    //3. t1 和 t2 都声明为const引用,所以返回类型是const才匹配
    

    如果返回的对象是被调用函数中的局部变量,则应返回对象,而不是引用,因为函数执行完毕时,局部引用对象将被析构回收

    Point Point::Operator+(const Point & p1, const Point & p2)
    {
      return Point(p1.x + p2.x, p1.y + p2.y);
    }
    
  • 模板函数

    模板函数(function template)参数列表通常由两种类型构成:

    1. 明确的类型

    2. 暂缓决定的类型

    template <typename T> void Display(string & msg, const vector<T> * vec)
    
    template <typename T> T CalScore(T t1, T t2);
    
    template<typename T1, typename T2> auto Sum(T1 t11, T2 t22) -> decltype(t11 + t22);
    
    //Usage: 用以上两个函数进行求和运算
    int a = 5;
    double b = 6.0;
    ::CalScore(a, b); //两个类型不一样,将报错;更改如下
    ::CalScore<double>(a, b); //Right
    
    //decltype (t1 + t2) t; //make t type the same with (t1 + t2)
    ::Sum(a, b); //因为t11 和 t22 类型不明 所以使用decltype关键字声明返回类型。因为auto可以自动推断t11 + t22 类型,所以也可以去掉 decltype 声明
    
    
  • inline函数

    内联函数的编译代码与其他程序代码 “内联” 起来了。 也就是说,编译器将使用相应的函数代码替换函数调用。程序无需跳到另一个位置处执行代码,再跳回。因此,运行速度稍快,但是占用更多内存。

    声明一个 inline 函数,只需在函数前加关键字 inline 即可,如:

    inline int Sum(int a, int b);
    
    • 将函数声明为 inline 函数,只是对编译器提出要求,编译器是否执行我们的要求,还需视编译器而定。

    • 那些体积小,常被调用,从事计算量不复杂的函数常被声明为 inline 函数

  • 虚函数

    ​ 在函数前关键字 virtual 定义函数为虚函数。

    如果方法是通过引用或者指针调用的,没有关键字 virtual 时,程序将根据引用的类型或者指针类型选择方法;如果有关键字virtual,程序将根据引用或指针指向的对象类型来选择方法。

    ​ 通常编译器处理虚函数会给每个对象添加一个隐藏成员。隐藏成员中保存了一个指向函数地址数组的指针。这种数组称为虚函数表(virtual functions table, vtbl)。虚函数表中存储了为类对象进行声明的虚函数的地址。调用虚函数时,程序将查看存储在对象中的vtbl地址,然后转向相应的函数地址表。

    ​ 使用虚函数在内存和执行速度方面有一定成本:

    • 每个对象将增大,增大量为存储空间
    • 对于每个类,编译器都会创建一个地址表
    • 对于每个函数调用,都需需要到 vtbl 中查找地址

    通常给基类提供一个虚析构函数,即使并不需要

    Animal.h
    
    class Animal
    {
    private:
      std::string name;
      int legs;
    public:
      Animal(const std::string& name, const int& legs);
      std::string GetName() const;
      int GetLegs() const;
      virtual void ShowInfo();
    };
    
    
    Horse.h
    
    class Horse : public Animal
    {
    private:
      int height;
    public:
      Horse(const std::string& name, const int& legs, const int& height);
      virtual void ShowInfo(); //void ShowInfo() override
    };
    
    Animal.cpp
    
    void Animal::ShowInfo()
    {
      std::cout << "Animal's name: " << name << ", it has " << legs << " legs" << std::endl;
    }
    
    
    Horse.cpp
    
    Horse::Horse(const std::string& name,const int& legs,const int& height)
    : Animal(name, legs)
    {
      this->height = height;
    }
    
    void Horse::ShowInfo()
    {
      std::cout << "Animal's name: "<<GetName() << ", it has " << GetLegs() << " legs, it's height: "<< this->height << std::endl;
    }
    
    • Usage
      
      Animal animal("sheep", 4);
      Horse horse("horse", 4, 1);
      animal.ShowInfo();
      horse.ShowInfo();
    
      Animal& an = animal;
      Animal& ho = horse;
      an.ShowInfo();
      ho.ShowInfo();
    
      Animal* ani = &animal;
      Animal* hor = &horse;
      ani->ShowInfo();
      hor->ShowInfo();
    
    
    • virtual void ShowInfo()
    Animal's name: sheep, it has 4 legs
    Animal's name: horse, it has 4 legs, it's height: 1
    Animal's name: sheep, it has 4 legs
    Animal's name: horse, it has 4 legs, it's height: 1
    Animal's name: sheep, it has 4 legs
    Animal's name: horse, it has 4 legs, it's height: 1
    
    • void ShowInfo() 去掉 virtual 时
    Animal's name: sheep, it has 4 legs
    Animal's name: horse, it has 4 legs, it's height: 1
    Animal's name: sheep, it has 4 legs
    Animal's name: horse, it has 4 legs
    Animal's name: sheep, it has 4 legs
    Animal's name: horse, it has 4 legs
    

    如果要重新定义继承方法,要确保与原型完全相同。像 ShowInfo(Animal &animal) 将会覆盖 ShowInfo(). 如果返回类型是基类引用或指针,则可修改为指向派生类的引用或指针(新出现的特例)。这种特性称为 返回型协变(covariance of return type), 因为允许返回类型随类型变化而变化。如果不与原型相同,则原有函数将被隐藏,派生类对象无法访问。

  • 虚析构函数

    virtual ~Animal() = default
    
    • 使用虚析构函数可以确保正确的析构函数被调用
  • 静态/动态联编

    ​ 将源代码中函数调用解释为执行特定的函数代码块称为函数名联编(binding)。

最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 204,293评论 6 478
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 85,604评论 2 381
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 150,958评论 0 337
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 54,729评论 1 277
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 63,719评论 5 366
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 48,630评论 1 281
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 38,000评论 3 397
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 36,665评论 0 258
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 40,909评论 1 299
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 35,646评论 2 321
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 37,726评论 1 330
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 33,400评论 4 321
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 38,986评论 3 307
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 29,959评论 0 19
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 31,197评论 1 260
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 44,996评论 2 349
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 42,481评论 2 342

推荐阅读更多精彩内容