C++C++雾中风景4:多态引出的迷惑,对象的正片?

C++作为同样宗面向对象的言语,自然有了面向对象的老三要命特征:封装,继承,多态。在念多态性质的长河遭到,发现了C++与另外语言很怪之分(坑?)。在C++中的=操作符的采取以及C++呈现的内存模型似乎并无是本人所习惯的模式,在拷贝与援两独例外操作间摇摆,还是很轻写有存在问题的代码,所以也就引出了今立首文章,我们来聊聊=操作符背后的故事。

1.聊意外的多态

来,先上代码,我们打点滴段落要发挥多态性质的代码来看看,奇怪在什么地方。

class bird {
public:
    virtual void fly() {
        cout << "I can fly." << endl;
    }
};

class penguin:public bird {
public:
    void fly() {
        cout << "I can't fly." << endl;
    }
}; 

地方是片只持续关系的类定义。penguin(企鹅)类继承了bird类。在bird类似之中fly()函数是一个virtual函数,它可吃penguin蒙。我们省科学的多态代码应该怎么编写:

int main() {
    bird* b1;
    penguin p; 

    b1 = &p;
    b1->fly();   //打印出:"I can't fly." 
}

编译器通过指针的情,而非是它们的类,来判定该调用的函数。因此,由于
penguin的对象的地点存储于bird指南针中,所以会见调用对应之fly()函数。
故每个bird的子类都得以一个函数fly()的单独实现。这即是多态的运用办法。可以生多独不等之子类,都含有同一个称呼但具备不同实现的函数。

啊哈,这有些看押起还充分到。但是熟悉JavaPython的程序员应该会及自己一样写来接近于下的代码吧:

int main() {
    penguin p;
    bird b = p; 
    b.fly(); //打印出:"I can fly."    
}

FxxK,这尚是无是自我熟悉的多态?为什么输出的情节及本人想象的未平等。不行,我得重新试试一试试其他方式。

int main() {
    penguin p;
    ((bird)p).fly(); //同样是打印出:"I can fly."    
}

2.起了什么问题呢?

吓吧,上面两段落代码我怀念会为多JavaPython的程序员发困惑,看起C++和咱们耳熟能详的言语想去死远。其实,这就回来我们今天一经聊的主题,接下我们逐条来分析及有数截代码:

int main() {
    penguin p;
    bird b = p; 
    b.fly(); //打印出:"I can fly."    
}

实质上这段代码最基本的触及是做明白bird b =
p
报句被之=操作符真正代表的意义。

以说明是=操作符,我们后续羁押下就段代码。

int main() {
    penguin p;
    bird &b = p; 
    b.fly(); //打印出:"I can’t fly."    
}

发出麻痹有特别神奇,让我们困惑的题材解决,只不过添加了一个&操作符。
在C++之中,= 操作符代表一个正片

  • bird b = p
    表示b是一个bird对象,通过p拷贝,重新生成一个新的bird对象。所以马上是一个拷贝操作,拷贝的凡一个目标。
  • bird &b = p
    表示b是一个bird对象的援,通过p的地址拷贝,重新生成一个新的bird对象的援。所以马上吗是一个拷贝操作,拷贝的凡一个目标引用。所以经过这引用,动态调用到p对象真正的函数。

吓了,解释了上同截代码之后,我们继承看第二段落代码。

int main() {
    penguin p;
    ((bird)p).fly(); //同样是打印出:"I can fly."    
}

此地为何我们强制类型转换之后,还是迫于输出我们纪念使的结果为?那是坐

除却指针与援类型,C++编译器在编译阶段通过品种静态确定调用函数的地方。
经这词话,我们为不难理解上一致段代码输出的结果,所以我们如果再好的施用多态,一定要以好指针和援。

3.其它语言的迷离的解析

  • Java
    面面俱到放弃了指针与目标拷贝的操作,所以Java之中的=全都是拷贝的对象的援。也就算是咱说的之浅拷贝。(对象拷贝是深拷贝,因为变化新的目标,和原目标不行使同一的内存空间).

  • Python
    同Java一般,都是目标引用。唯一不同之凡,Python是动态语言,在贯彻多态的时段,依赖还多是鸭类型要是非是相仿原生的连续关系了。

  • Golang
    及Python相同,依赖鸭子类型。