-
C++中的引用
像常量型指针。 (const在*右边使指针本身成为const) 要求: 1.必须初始化 2.只能指向一个对象 3.没有null引用 参数传递规则: 传值方式需要调用ctr and dtr,然而如果不想改变参数,则可以通过常量引用传递,它仅需要将地址压栈。 -
拷贝构造函数
X(X&) 1.按值传递和返回 1). 传递和返回大对象 2). 函数调用栈的框架 函数参数 返回地址 局部变量 3). 重入意味着任何函数可以中断任何其他的函数,包括与之相同的函数。因此,如果把返回值放 在全局区域,我们可能又返回到相同的函数中,这将重写返回值。对于递归也是同样道理。 唯一安全的返回场所是寄存器,问题是当寄存器没有足够大用于存放返回值时该怎么做。 答案是把返回值的地址像一个函数参数一样压栈,让函数直接把返回值信息拷贝到目的地。这 样做不仅解决了问题,而且效率更高。 4). 位拷贝(b i t c o p y)与初始化 2. 拷贝构造函数 如果设计了拷贝构造函数,当从现有的对象创建新对象时,编译器将不使用位拷贝 ( b i t c o p y )。编译器总是调用我们的拷贝构造函数。 3.缺省拷贝构造函数 最好的方法是创建自己的拷贝构造函数而不让编译器创建。这样就能保证程序在我们的控 制之下。 4. 拷贝构造函数方法的选择 1). 防止传值方式传递 声明一个私有( p r i v a t e)拷贝构造函数。 2). 改变外部对象的函数 除非我们打算通过地址修改外部对象(这个地址通过非c o n s t指针传递),要不然都用c o n s t引用传递地址。 -
指向成员的指针(简称成员指针)
只有把这个偏移和具体对象的开始地址结合,才能得到实际地址。成员指针的语法要求选择一个对象的同时逆向引用成员指针。 -
对象创建
当一个C + +对象被创建时,有两件事会发生。 1) 为对象分配内存。 2) 调用构造函数来初始化那个内存。 C + +中的解决方案是把创建一个对象所需的所有动作都结合在一个称为n e w的运算符里。 当用n e w(n e w的表达式)创建一个对象时,它就在堆里为对象分配内存并为这块内存调用构 造函数。因此,如果我们写出下面的表达式 foo *fp = new foo(1,2) ; 在运行时等价于调用m a l l o c ( s i z e o f ( f o o ) ),并使用( 1,2)作为参数表来为f o o调用构造函数, 返回值作为t h i s指针的结果地址。 n e w表达式的反面是d e l e t e表达式。d e l e t e表达式首先调用析构函数,然后释放内存(经常 是调用free( ))。正如n e w表达式返回一个指向对象的指针一样, d e l e t e表达式需要一个对象的 地址。 delete fp ; 用于数组的new和delete foo* fp = new foo[100] ; delete fp ; // Not the desired effect delete []fp ; -
重载new和delete
重载运算符n e w还有其他两个不常见的用途。 1) 可能想要在内存的指定位置上放置一个对象。这对于面向硬件的内嵌系统特别重要,在 这个系统中,一个对象可能和一个特定的硬件是同义的。 2) 可能想在调用new时,可以从不同的内存分配器中选择。 这两种情形都用相同的机制解决:重载的运算符n e w可以带多于一个的参数。像前面所看 到的,第一个参数总是对象的长度,它是在内部计算出来的并由编译器传递。但其他参数可以 由我们自己定义:一个放置对象的地址、一个对内存分配函数或对象的引用、或其他方便的任何设置。 -
C + +最重要的性能之一是代码重用.
简单地创建一个包含已存在的类对象的新类,这称为组合 创建一个新类作为一个已存在类的类型,采取这个已存在类的形式,对它增加代码,但不修改它。这个有趣的活动被称为继承. 组合: 在这个类中,数值成员是私有的,所以对于将类型X 的一个对象作为公共对象嵌入到一个新 类内部,是绝对安全的。 访问嵌入对象(称为子对象)的成员函数只须再一次选择成员。 如果嵌入的对象是p r i v a t e的,可能更具一般性,这样,它们就变成了内部实现的一部分. 继承: 类体的开括号前面,加一冒号和基类名(或加多个类,对于多重继承)。这样做,就自 动地得到了基类中的所有数据成员和成员函数。 1)构造函数的初始化表达式表 每一层,首先调用基类构造函数,然后调用成员对象构造函数 2)对私有继承成员公有化 当私有继承时,基类的所有public成员都变成了private。如果希望它们中的任何一个是可 视的,只要用派生类的p u b l i c选项声明它们的名字即可。 3)关键字p r o t e c t e d对于继承有特殊的意义。在理想世界中, p r i v a t e成员总是严格私有的,但在实际项目中,有时希望某些东西隐藏起来,但仍允许其派生类的成员访问。 于是关键字p r o t e c t e d派上了用场。它的意思是:“就这个类的用户而言,它是p r i v a t e的,但它可被从这个类继承来的任何类使用。” 4)任何向上映射都会损失对象的类型信息, 如果说 wind w; //instrument 为 wind 父类 instrument * ip = &w; 编译器只能把i p作为一个i n s t r u m e n t指针处理。这就是说,它不知道i p实际上指向w i n d的对象。 所以,当调用p l a y ( )成员函数时,如果使用 i p - > p l a y ( m i d d l e C ) ; 编译器只知道它正在对于一个i n s t r u m e n t指针调用p l a y ( ),并调用i n s t r u m e n t∷p l a y ( )的基本版本, 而不是它应该做的调用w i n d∷p l a y ( )。这样将会得到不正确的结果。 这是一个重要的问题,将在介绍面向对象编程的第三块基石:多态性(在C + + 中用v i r t u a l函数实现)来解决。 -
C++如何实现晚捆绑
编译器对每个包含虚函数的类创建一个表(称为V TA B L E)。在 V TA B L E中,编译器放置特定类的虚函数地址。在每个带有虚函数的类中,编译器秘密地置一 指针,称为v p o i n t e r(缩写为V P T R),指向这个对象的V TA B L E。通过基类指针做虚函数调用 时(也就是做多态调用时),编译器静态地插入取得这个V P T R,并在V TA B L E表中查找函数地 址的代码,这样就能调用正确的函数使晚捆绑发生。 在派生类中v i r t u a l函数的重定义通常称为越位。 对于特定的函数,为了引起晚捆绑, C + +要求在基类中声明这个函数时使用v i r t u a l关键字。 晚捆绑只对v i r t u a l起作用,而且只发生在我们使用一个基类的地址时,并且这个基类中有 v i r t u a l函数,尽管它们也可以在更早的基类中定义。 -
纯虚函数
virtual void x() = 0; 这样做,等于告诉编译器在V TA B L E中为函数保留一个间隔,但在这个特定间隔中不放地 址。只要有一个函数在类中被声明为纯虚函数,则V TA B L E就是不完全的。包含有纯虚函数的 类称为纯抽象基类。 如果使用对象而不是使用地址或引用进行向上映射,发生的事情会使我们吃惊:这个对象 被“切片”,直到所剩下来的是适合于目的的子对象。 可以通过在基类中放置纯虚函数来防止对象切片。 RTTI: run-time type indentification 向下类型转换基类指针到派生类指针的问题。 友情链接: [https://www.cnblogs.com/findumars/p/6358194.html](https://www.cnblogs.com/findumars/p/6358194.html)
C++编程思想-引用和拷贝构造函数+对象创建动态+继承和组合+多态性和虚函数
最新推荐文章于 2024-03-20 10:43:02 发布
本文深入探讨C++中的引用、拷贝构造函数、成员指针、对象创建与删除、new/delete运算符重载、代码重用策略如组合与继承,以及多态性的实现机制等核心概念。
893

被折叠的 条评论
为什么被折叠?



