the third day
学习目录:
一.引用
二.继承
三.c++继承时的名字遮蔽
四.c++派生类的构造函数和析构函数
五.多继承
六.命名冲突(多继承下)
七.虚继承和虚基类(解决命名冲突)
八.c++向上转型
学习总结
一.引用:一种比指针更加便捷的传递聚合类型数据的方式,那就是引用(Reference),引用可以看做是数据的一个别名,通过这个别名和原来的名字都能够找到这份数据,相当于人的绰号。
引用格式: type &name = data;
type 是被引用的数据的类型
name 是引用的名称
data 是被引用的数据
注意:1.引用必须在定义的同时初始化,定义时加&,使用时不加&,并且以后也要从一而终,不能再引用其它数据,这有点类似于常量(const 变量)。
2.引用作为函数返回值时不能返回局部数据的引用。比如:
int &fun()
{
int x=10;
int &y=x;
return y; //这是不允许的
}
二.继承:可以理解为一个类从另一个类获取成员变量和成员函数的过程,例如:类 B 继承于类 A,那么 B 就拥有 A 的成员变量和成员函数,被继承的类称为父类或基类,继承的类称为子类或派生类,派生类除了拥有基类的成员,还可以定义自己的新成员,以增强类的功能。
继承的一般语法为: 比如:
class 派生类名:[继承方式] 基类名 class A A是基类
{ {};
派生类新增加的成员; class B:public A B派生类
}; {};
基类public->派生类中属性 基类protected->派生类中属性 基类private->派生类中属性
public继承 public protected private
proteced继承 protected protected private
private继承 private private private
注意:using关键字可以改变基类成员在派生类中的访问权限:将protected改成public,将public改成private。
三.c++继承时的名字遮蔽
定义:派生类中的新增的成员函数和从基类继承的成员函数的名称相同会造成名字遮蔽。
特点:在main函数调用时,调用的是派生中新增的成员函数,而基类中的成员函数被遮蔽(就会产生只要函数名称一样就会产生遮蔽)。
注意:1.如果要调用基类中的成员函数要用域解析符。
2.基类成员和派生类的成员函数不会构成重载。
比如:
class A
{
public:
void show() //被遮蔽
{
cout<<"A"<<endl;
}
}
class B:public A
{
public:
void show()
{
cout<<"B"<<endl;
}
}
int main()
{
B b;
b.show(); //调用的是B类中的show()函数
}
四.c++派生类的构造函数和析构函数
1.构造函数
特点:基类的构造函数是不会被继承的,但是可以被派生函数调用;
构造函数调用顺序:派生类构造函数总是先调动基类构造函数再执行其他代码
比如:
Student::Student(char *name,int age):People(name),age(age){}
2.析构函数
调用析构函数的顺序和调用构造函数的顺序相反。
五.多继承
定义:一个派生类有两个或多个基类。
比如:
class A:public B,public C
{
}
注意:基类构造函数的调用顺序和它们在派生类构造函数中出现的顺序无关,而是和声明派生类时基类出现的顺序相同
六.命名冲突
定义:当两个或多个基类成员中有同名成员时,如果直接访问该成员就会产生命名冲突。
解决方法:可以在成员名字前加域解析符。
比如:
class A
{
public:
void show();
}
class B
{
public:
void show();
}
class C:public A,public B
{
public:
void display()
{
A::show();
B::show();
}
}
七.虚继承和虚基类
定义:在继承方式前面加上 virtual 关键字就是虚继承
使用条件:多继承
菱形继承:A类有成员m_a,B类和C类继承于A,则B类和C类都有m_a成员,D类继承于B和C类,而D在调用m_a时不知是B类的m_a还是C类的m_a,这就产生了二义性
解决方法:在B类和C类的成员函数前加virtual关键字,这时m_a就成了共享成员
八.c++向上转型
定义:将派生类赋值给基类,包括将派生类对象赋值给基类对象、将派生类指针赋值给基类指针、将派生类引用赋值给基类引用,这在 C++ 中称为向上转型
特点:将派生类中的成员变量赋值给基类的成员变量,不会影响成员函数和this指针,而赋值时派生类中新增的成员变量会被自动舍弃,如果每个类中都有show()函数会造成遮蔽现象,但赋值后调用show()是调用本身的show()函数。
比如:
#include <iostream>
using namespace std;
//基类
class A{
public:
A(int a);
public:
void display();
public:
int m_a;
};
A::A(int a): m_a(a){ }
void A::display(){
cout<<"Class A: m_a="<<m_a<<endl;
}
//派生类
class B: public A{
public:
B(int a, int b);
public:
void display();
public:
int m_b;
};
B::B(int a, int b): A(a), m_b(b){ }
void B::display(){
cout<<"Class B: m_a="<<m_a<<", m_b="<<m_b<<endl;
}
int main(){
A a(10);
B b(66, 99);
//赋值前
a.display();
b.display();
cout<<"--------------"<<endl;
//赋值后
a = b;
a.display();
b.display();
return 0;
}
输出结果:
class A:m_a=10;
class B:m_a=66,m_b=99;
-----------------------------
class A:m_a=66;
class B:m_a=66,m_b=99;
一天到晚忙啊!