C++复习小知识点总结

一:C++引用
1:引用可以看做是数据的一个别名,通过这个别名和原来的名字都能够找到这份数据,例如周树人和鲁迅指的是同一人;
2:引用用&替代了指针的*,定义为:type &name = data;即为data起了一个别名:name,改变name的值会影响data的值,引用必须在定义的同时初始化,并且以后也要从一而终,不能再引用其它数据,这有点类似于常量(const 变量)
3:引用在定义时需要添加&,在使用时不能添加&,使用时添加&表示取地址。使用时,如果cout << &name << endl;则输出data的内存地址;
4:若不希望用别名来修改原值,可以加上const限制符,此时课通过原值来修改别名的值(我也不知道这样做有啥用手动/xk,先记下吧)
5:
传递指针:
定义:void fun(int *p1, int *p2)
调用:fun(&num1,&num2)
按引用传参:
定义:void fun (int &p1, int &p2)
调用:fun(num1, num2)
以上两种方法都可以改变原数值
6:引用还可以作为函数返回值;但尽量不要返回局部变量的引用,函数执行完毕后局部数据就会被销毁,有可能在下次使用时数据就不存在了。

二:继承与派生
1:写法:class 派生类名:[继承方式] 基类名
继承方式包括 public(公有的)、private(私有的)和 protected(受保护的),此项是可选的,如果不写,那么默认为 private。我们将在下节详细讲解这些不同的继承方式。
2:
public继承方式
基类中所有 public 成员在派生类中为 public 属性;
基类中所有 protected 成员在派生类中为 protected 属性;
基类中所有 private 成员在派生类中不能使用。

protected继承方式
基类中的所有 public 成员在派生类中为 protected 属性;
基类中的所有 protected 成员在派生类中为 protected 属性;
基类中的所有 private 成员在派生类中不能使用。

private继承方式
基类中的所有 public 成员在派生类中均为 private 属性;
基类中的所有 protected 成员在派生类中均为 private 属性;
基类中的所有 private 成员在派生类中不能使用。

3:基类的 private 成员是能够被继承的,并且(成员变量)会占用派生类对象的内存,它只是在派生类中不可见,在派生类中访问基类 private 成员的唯一方法就是借助基类的非 private 成员函数,如果基类没有非 private 成员函数,那么该成员在派生类中将无法访问,例如getxxxx函数;

4:使用 using 关键字可以改变基类成员在派生类中的访问权限,只能改变基类中 public 和 protected 成员的访问权限,不能改变 private 成员的访问权限,因为基类中 private 成员在派生类中是不可见的,根本不能使用,所以基类中的 private 成员在派生类中无论如何都不能访问;

5:C++继承时如果自己定义的成员函数与继承函数重名,则会遮蔽从基类继承来的重名函数;基类成员函数和派生类成员函数不构成重载,无论传递参数如何不一样,不构成重载。
例如:
基类base中:public定义
void func();
void func(int);
继承类中定义:
void func(char *);
void func(bool);
继承类中定义对象可以调用含字符参数的fun函数,可以调用bool类型参数的fun函数,直接调用int类型参数的fun函数会报错,可以使用对象名.base::fun(int)类型调用

6:类的构造函数不能被继承,可以在派生类的构造函数中调用基类的构造函数;如:
Student::Student(char *name, int age, float score): People(name, age), m_score(score)
派生类Student,构造函数调用基类People的构造函数,派生类构造函数总是先调用基类构造函数再执行其他代码且基类构造函数不会被继承,不能当做普通的成员函数来调用。换句话说,只能将基类构造函数的调用放在函数头部,不能放在函数体中。

7:单继承
构造函数的调用顺序:
从基类逐步到第一层继承类,到下一层继承类
析构函数的顺序:
为从最下继承类到最后的基类(与构造函数顺序相反)
若显示写了基类构造函数,则编译器不会自动生成无参构造函数,如需要用,则需要自行定义

8:一个派生类可以有两个或多个基类,若多个基类中有重名函数,继承类在调用时需要用作用域符号指定调用哪一个基类的函数,例如:C继承A,B且A,B都有函数show(),C在调用show函数时需要写成:A::show()调用A的

9:虚继承:成员变量重名冲突,例如
在这里插入图片描述
B,C继承A,D继承B,C,假设A中有成员变量a,若果D的对象要使用成员变量a,此时计算机不知道要使用A->B->D的a还是A->C->D的a
为了解决多继承时的命名冲突和冗余数据问题,C++ 提出了虚继承,使得在派生类中只保留一份间接基类的成员。
在继承方式前面加上 virtual 关键字就是虚继承,如:
class B: virtual public A{
}
class C: virtual public A{
}

假设 B 定义了一个名为 x 的成员变量,当我们在 D 中直接访问 x 时,会有三种可能性:
如果 A 和 C 中都没有 x 的定义,那么 x 将被解析为 B 的成员,此时不存在二义性。
如果 A 或 C 其中的一个类定义了 x,也不会有二义性,派生类的 x 比虚基类的 x 优先级更高。
如果 B 和 C 中都定义了 x,那么直接访问 x 将产生二义性问题。
建议:只有在比较简单和不易出现二义性的情况或实在必要时才使用多继承,能用单一继承解决的问题就不要使用多继承。

在虚继承中,虚基类是由最终的派生类初始化的,换句话说,最终派生类的构造函数必须要调用虚基类的构造函数。跟普通继承不同,在普通继承中,派生类构造函数中只能调用直接基类的构造函数,不能调用间接基类的
如果D::D(int a, int b, int c, int d): A(a), B(90, b), C(100, c), m_d(d){ }
在最终派生类 D 的构造函数中,除了调用 B 和 C 的构造函数,还调用了 A 的构造函数,这说明 D 不但要负责初始化直接基类 B 和 C,还要负责初始化间接基类 A。而在以往的普通继承中,派生类的构造函数只负责初始化它的直接基类,再由直接基类的构造函数初始化间接基类,用户尝试调用间接基类的构造函数将导致错误。
现在采用了虚继承,虚基类 A 在最终派生类 D 中只保留了一份成员变量 m_a,如果由 B 和 C 初始化 m_a,那么 B 和 C 在调用 A 的构造函数时很有可能给出不同的实参,这个时候编译器就会犯迷糊,不知道使用哪个实参初始化 m_a。

为了避免出现这种矛盾的情况,C++ 干脆规定必须由最终的派生类 D 来初始化虚基类 A,直接派生类 B 和 C 对 A 的构造函数的调用是无效的。在第 50 行代码中,调用 B 的构造函数时试图将 m_a 初始化为 90,调用 C 的构造函数时试图将 m_a 初始化为 100,但是输出结果有力地证明了这些都是无效的,m_a 最终被初始化为 50,这正是在 D 中直接调用 A 的构造函数的结果。

如果:D::D(int a, int b, int c, int d): B(90, b), C(100, c), A(a), m_d(d){ }
虽然我们将 A() 放在了最后,但是编译器仍然会先调用 A(),然后再调用 B()、C(),因为 A() 是虚基类的构造函数,比其他构造函数优先级高。如果没有使用虚继承的话,那么编译器将按照出现的顺序依次调用 B()、C()、A()。
与多继承调用顺序差别:单继承中构造函数的执行顺序是由基类开始一次往下

10:C++将派生类赋值给基类(向上转型)
类其实也是一种数据类型,也可以发生数据类型转换,不过这种转换只有在基类和派生类之间才有意义,并且只能将派生类赋值给基类,包括将派生类对象赋值给基类对象、将派生类指针赋值给基类指针、将派生类引用赋值给基类引用,这在 C++ 中称为向上转型(Upcasting)。相应地,将基类赋值给派生类称为向下转型(Downcasting)
向下转型有风险

11:除了可以将派生类对象赋值给基类对象(对象变量之间的赋值),还可以将派生类指针赋值给基类指针(对象指针之间的赋值)
参考:

http://c.biancheng.net/view/2284.html

  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值