文章目录
- 一、继承的本质和原理
- 二、重载、隐藏和覆盖
- 三、基类与派生类的转换
一、继承的本质和原理
继承的本质:a. 代码的复用 b.
类和类之间的关系:
组合:a part of… 一部分的关系
继承:a kind of… 一种的关系
总结:
- 外部只能访问对象public的成员,protected和private的成员无法直接访问。
- 在继承结构中,派生类从基类可以继承过来private的成员,但是派生类却无法直接访问。
- protected和private的区别?
在基类中定义的成员,想被派生类访问,但是不想被外部访问,那么在基类中,把相关成员定义成protected保护的;
如果派生类和外部都不打算访问,那么在基类中,就把相关成员定义成private私有的。 - 默认的继承方式是什么?
要看派生类是用class定义的,还是struct定义的。
class定义派生类,默认继承方式就是private私有的。
struct定义派生类,默认继承方式就是public私有的。 - 派生类从继承可以继承来所有的成员(变量和方法),除过构造函数和析构函数
- 派生类怎么初始化从基类继承来的成员变量呢?答:通过调用基类相应的构造函数来初始化。
- 派生类的构造函数和析构函数,负责初始化和清理派生类部分
派生类从基类继承来的成员的初始化和清理由谁负责呢?是由基类的构造和析构函数来负责。 - 派生类对象构造和析构的过程是:
1.派生类调用基类的构造函数,初始化从基类继承来的成员;
2.调用派生类自己的构造函数,初始化派生类自己特有的成员;
…派生类对象的作用域到期了
3.调用派生类的析构函数,释放派生类成员可能占用的外部资源(堆内存,文件);
4.调用基类的析构函数,释放派生类内存中,从基类继承来的成员可能占用的外部资源(堆内存,文件)。
#include <iostream>
using namespace std;
class Base {
public:
Base(int data)
: ma(data)
{
cout << "Base()" << endl;
}
~Base() {
cout << "~Base()" << endl;
}
protected:
int ma;
};
class Derive : public Base {
public:
Derive(int data)
//: ma(data) //"Base":没有合适的默认构造函数可用
: Base(data)
, mb(data)
{
cout << "Derive()" << endl;
}
~Derive() {
cout << "~Derive()" << endl;
}
private:
int mb;
};
int main() {
Derive d(20);
return 0;
}
二、重载、隐藏和覆盖
- 重载关系
一组函数要重载,必须处在同一个作用域当中;而且函数名字相同,参数列表不同。 - 隐藏(作用域的隐藏)的关系
在继承结构当中,派生类的同名成员,把基类的同名成员给隐藏调用了。 - 覆盖
基类和派生类的方法,返回值、函数名以及参数列表都相同,而且基类的方法是虚函数,那么派生类的方法就自动处理成虚函数,它们之间成为覆盖关系。
#include <iostream>
using namespace std;
class Base {
public:
Base(int data)
: ma(data)
{
cout << "Base()" << endl;
}
~Base() {
cout << "~Base()" << endl;
}
void show() { cout << "Base::show()" << endl; }
void show(int) { cout << "Base::show(int)" << endl; }
protected:
int ma;
};
class Derive : public Base {
public:
//"Base":没有合适的默认构造函数可用
Derive(int data = 20)
: Base(data)
, mb(data)
{
cout << "Derive()" << endl;
}
~Derive() {
cout << "~Derive()" << endl;
}
void show() { cout << "Base::show()" << endl; }
private:
int mb;
};
int main() {
Derive d;
d.show();
// 优先找的是派生类自己作用域的show名字成员; 没有的话,才去基类里找
d.show(10); //"Derive::show": 函数不接受 1 个参数
return 0;
}
三、基类与派生类的转换
把继承结构,也说成从上(基类)到下(派生类)的结构。
#include <iostream>
using namespace std;
class Base {
public:
Base(int data = 10)
: ma(data)
{
cout << "Base()" << endl;
}
~Base() {
cout << "~Base()" << endl;
}
void show() { cout << "Base::show()" << endl; }
void show(int) { cout << "Base::show(int)" << endl; }
protected:
int ma;
};
class Derive : public Base {
public:
//"Base":没有合适的默认构造函数可用
Derive(int data = 20)
: Base(data)
, mb(data)
{
cout << "Derive()" << endl;
}
~Derive() {
cout << "~Derive()" << endl;
}
void show() { cout << "Base::show()" << endl; }
private:
int mb;
};
int main() {
Base b(10);
Derive d(20);
// 基类对象b <- 派生类对象d 类型从下到上的转换 Y
b = d;
// 派生类对象d <- 基类对象b 类型从上到下的转换 N
// d = b;
// 基类指针(引用) <- 派生类对象 类型从下到上的转换 Y
Base *pb = &d;
pb->show(); // 只能访问基类部分Base::show() ((Derive*)pb)->show();
pb->show(10); // 只能访问基类部分Base::show(int)
// 派生类指针(引用) <- 基类对象 类型从上到下的转换 N
// Derive *pd = &b; // Derive *pd = (Derive*)&b; 类型强转不安全,涉及了内存的非法访问!
return 0;
}
总结:在继承结构中进行上下的类型转换,默认只支持从下到上的类型的转换OK