继承与派生
目的:不影响原来的类,不改变原来类的代码,实现对于功能的扩展。
内容:基本概念 && 名词解释 语法实现 深入分析 菱形继承
继承与派生(名词解释)
继承:
一种在已有类的基础上创建新类的方式(类与类之间的关系);
新创建的类叫派生类或子类——对应基类和父类
继承与派生是同一过程的不同(角度)描述方式,站在子类角度,从父类继承过来,站在父类角度,派生出去。
继承分类:
- 单继承:只有一个父类(基类);
- 多继承:多个父类(基类)。
继承方式
语法
一、单继承
class 父类名
{
};
class 子类名 : 继承权限 父类名
{
};
二、多继承
class 父类名1
{
};
class 父类名2
{
};
……
class 子类名 : 继承权限 父类名1, 继承权限 父类名2,... , 继承权限n 父类名n
{
};
三、继承权限
- 公有继承 public
- 私有继承 private
- 保护继承 protected
注意:
继承是子类继承父类的全部成员(函数、数据),但是受访问权限限制。
权限授予
父类成员的访问权限\继承权限 | 公有继承 public | 私有继承 private | 保护继承 protected |
---|---|---|---|
public | public | private | protected |
private | 不可访问 | 不可访问 | 不可访问 |
protected | protected | private | protected |
多级继承:通过父子关系的继承权限去分析。
举例:
#include <iostream>
using namespace std;
class Father
{
public:
Father();
~Father();
public:
int pub;
void pub_func();
private:
int pri;
void pri_func();
protected:
int pro;
void pro_func();
};
class Son : public Father
{
public:
Son();
~Son();
public:
int num;
void test_func()
{
this->num;
// 公有权限可以访问
this->pub;
this->pub_func();
// 保护权限在类的内部可以访问
this->pro;
this->pro_func();
}
private:
};
int main()
{
cout << "sizeof(Father)" << sizeof(Father) << endl;
cout << "sizeof(Son)" << sizeof(Son) << endl;
Son obj_son;
obj_son.pub_func();
return 0;
}
Father::Father()
{
}
Father::~Father()
{
}
void Father::pub_func()
{
}
void Father::pri_func()
{
}
void Father::pro_func()
{
}
Son::Son()
{
}
Son::~Son()
{
}
父子关系
派生类的构成
构造和析构不会继承,其他成员可以被继承;
派生类的成员和基类成员的成员名相同时,基类的成员会被隐藏,需要使用基类的成员时,需在成员名前加基类类名+作用域符。
#include <iostream>
using namespace std;
class Father
{
public:
Father();
~Father();
public:
int val;
int num;
};
class Father_1
{
public:
Father_1();
~Father_1();
public:
int val;
};
class Son : public Father, public Father_1
{
public:
Son();
~Son();
public:
int num;
};
int main()
{
Son obj_son;
cout << "obj_son.num = " << obj_son.num << endl;
cout << "obj_son.Father::num = " << obj_son.Father::num << endl;
/* 来自两个不同Father的同名成员 */
cout << "obj_son.Father::val = " << obj_son.Father::val << endl;
cout << "obj_son.Father_1::val = " << obj_son.Father_1::val << endl;
return 0;
}
/* Father */
Father::Father()
{
val = 10;
num = 12;
}
Father::~Father()
{
}
/* Father_1 */
Father_1::Father_1()
{
this->val = 1;
}
Father_1::~Father_1()
{
}
/* Son */
Son::Son()
{
num = 99;
}
Son::~Son()
{
}
输出:
派生类和基类的关系
父类对象可以用子类对象赋值,子类对象不能用父类对象赋值(子类对象的范围比父类对象的范围大,父类对象无法赋慢)
父类指针可以指向子类对象,但子类指针不能指向父类对象(子类指针读取的内存范围比父类指针大)
#include <iostream>
using namespace std;
class Father
{
public:
Father();
~Father();
public:
};
class Son : public Father
{
public:
Son();
~Son();
};
int main()
{
Father obj_fat;
Son obj_son;
Father* p_fat = NULL;
Son* p_son = NULL;
// 父类对象可以用子类对象赋值,子类对象不能用父类对象赋值(子类对象的范围比父类对象的范围大,父类对象无法赋慢)
obj_fat = obj_son;
// obj_son = obj_fat;
// 父类指针可以指向子类对象,但子类指针不能指向父类对象(子类指针读取的内存范围比父类指针大)
p_fat = &obj_son;
// p_son = &obj_fat;
return 0;
}
/* Father */
Father::Father()
{
}
Father::~Father()
{
}
/* Son */
Son::Son()
{
}
Son::~Son()
{
}
派生类构造和析构的顺序
在成员初始化列表可以调用构造函数,除此之外构造函数不能被主动调用。
#include <iostream>
using namespace std;
class Father
{
public:
Father();
Father(int n);
~Father();
public:
const int num;
};
class Son : public Father
{
public:
Son();
Son(int n, int v);
~Son();
public:
int val;
};
int main()
{
// Son obj_son;
// Son obj_son(3, 4);
Son obj_son(3, 4);
cout << " obj_son.num = " << obj_son.num
<< " obj_son.val = " << obj_son.val
<< endl;
return 0;
}
/* Father */
Father::Father() : num(0)
{
//num = 12;
cout << "父类的构造" << endl;
}
Father::Father(int n) : num(n)
{
//n = num;
cout << "父类的带参构造" << endl;
}
Father::~Father()
{
cout << "父类的析构" << endl;
}
/* Son */
Son::Son()
{
val = 10;
cout << "子类的构造" << endl;
}
// 在成员初始化列表可以调用构造函数,构造函数是不能被主动调用的。
Son::Son(int n, int v) : Father(n)
{
val = v;
cout << "子类的带参构造" << endl;
}
Son::~Son()
{
cout << "子类的析构" << endl;
}
输出:
菱形继承
类AA继承了两份来自类A的成员,多余了。
虚继承
解决多余继承(如菱形继承)的情况。
关键字:virtual
#include <iostream>
using namespace std;
class A
{
public:
int n = 5;
};
class A_1 : virtual public A
{
public:
int a1;
};
class A_2 : virtual public A
{
public:
int a2;
};
class AA : public A_1, public A_2
{
public:
int aa;
};
int main()
{
AA obj_aa;
obj_aa.aa;
obj_aa.a1;
obj_aa.a2;
// obj_aa.n;
//cout << "obj_aa.A_1::n = " << obj_aa.A_1::n << endl;
//cout << "obj_aa.A_2::n = " << obj_aa.A_2::n << endl;
//cout << "obj_aa.A::n = " << obj_aa.A::n << endl;
cout << "sizeof(A_1) = " << sizeof(A_1) << endl;
cout << "sizeof(A_2) = " << sizeof(A_2) << endl;
cout << "sizeof(AA) = " << sizeof(AA) << endl;
cout << "sizeof(A*) = " << sizeof(A*) << endl;
cout << "sizeof(A_1*) = " << sizeof(A_1*) << endl;
cout << "sizeof(A_2*) = " << sizeof(A_2*) << endl;
cout << "sizeof(int) = " << sizeof(int) << endl;
return 0;
}
<未完待续>