前言
软件为visual studio2017,内容为C++学习笔记,以及相关的问题处理方法,目的是方便回顾和复习。 笔记来自于:黑马程序员C++教程。
一、继承是什么?
继承 是面向对象三大特性之一 。- 类与类之间存在存在特殊的关系,在定义一些类时,下级别的成员除了拥有上一级的共性,还有自己的特性。
- 因此,可以利用集成的技术,减少重复代码。
二、继承的基本语法
1.代码案例
# include <iostream>
using namespace std;
# include <string>
class BasePage {
public:
void header() {
cout << "首页、公开课、登录、注册...(公共头部)" << endl;
};
void footer() {
cout << "帮助中心、交流合作、站内地图...(公共底部)" << endl;
};
void left() {
cout << "Java、Python、C++、...(公共分类列表)" << endl;
};
};
class Java :public BasePage {
public:
void content() {
cout << "C++学科" << endl;
}
};
class Python :public BasePage {
public:
void content() {
cout << "Python学科" << endl;
}
};
class CPP :public BasePage {
public:
void content() {
cout<< "C++学科" <<endl;
}
};
void test01() {
cout<<"Java下载的视频页面如下:"<<endl;
Java ja;
ja.header();
ja.footer();
ja.left();
ja.content();
cout << "Python下载的视频页面如下:" << endl;
cout<<"_________________________________" <<endl;
Python py;
py.header();
py.footer();
py.left();
py.content();
cout << "C++下载的视频页面如下:" << endl;
cout << "_________________________________" << endl;
CPP cpp;
cpp.header();
cpp.footer();
cpp.left();
cpp.content();
}
int main() {
test01();
system("pause");
return 0;
}
2.继承的语法
- 继承的好处:
减少重复代码 。 - 语法:class
子类 :继承方式 父类 子类 也称为 派生类 父类 也称为 基类 class A:public B; A类被称为子类 或者 派生类 B类被称为父类 或者 基类
3.派生类(子类)中的成员特点
- 一类是从基类中
继承 过来的,一类是自己增加的成员 。 - 从基类中继承过来的表现为
共性 ,而新增成员体现了其个性。
三、继承方式
1、继承的语法:
class 子类 : 继承方式 父类 class 派生类 :继承方式 父类
2.继承方式一共有三种:
- 公共继承
- 保护继承
- 私有继承
3.代码示例
# include <iostream>
using namespace std;
# include <string>
class Base1 {
public:
int m_A;
protected:
int m_B;
private:
int m_C;
};
class son1 :public Base1
{
public:
void func() {
m_A = 10;
m_B = 20;
};
};
void test01() {
son1 s;
s.m_A = 20;
};
class Base2 {
public:
int m_A;
protected:
int m_B;
private:
int m_C;
};
class son2 :protected Base2 {
public:
void func() {
m_A = 10;
m_B = 20;
};
};
void test02() {
son2 s;
};
class Base3 {
public:
int m_A;
protected:
int m_B;
private:
int m_C;
};
class son3 :private Base3 {
public:
void func() {
m_A = 10;
m_B = 20;
};
};
void test03() {
son3 s;
}
class GrandSon3 :public son3 {
public:
void func() {
}
};
int main() {
system("pause");
return 0;
}
四、继承中的对象模型
1.代码示例
# include <iostream>
using namespace std;
# include <string>
class Base {
public:
int m_A;
protected:
int m_B;
private:
int m_C;
};
class Son :public Base {
public:
int m_D;
};
void test01()
{
cout << "sizeof(son)的大小为:" << sizeof(Son) << endl;
}
int main() {
test01();
system("pause");
return 0;
}
2.使用开发者命令提示符号
- 打开visualStudio2017下的开发者命令提示符号。
- 将XX.cpp文件,右键-打开文件所在文件夹,并复制路径。例如:F:…\继承方式
- (使用英文)进入到F盘中 —— F:。
- F: cd F:…\继承方式(文件路径)
- dir——查看当前文件包含内容。
- 报告单个类的布局:
cl /d1 reportSingleClassLayout类名 “文件名…cpp”
3.结论
父类中的私有成员也是被子类继承下去了,只是由编译器给隐藏后访问不到。
五、继承中构造和析构顺序
1.构造顺序
- 子类继承父类之后,当创建子类对象时,也会调用父类的构造函数,
先 创建父类对象 ,然后 创建子类对象 。
2.析构顺序
先 创建父类对象 ,然后 创建子类对象 。先析构子类 对象,然后再析构父类 对象。
3.代码示例
4.总结
- 继承中构造和析构顺序如下:
先构造父类 先调用父类函数,再构造子类 调用子类的构造函数,析构 的顺序和构造的顺序相反。 - 继承的时候,
构造和析构 顺序原理类似于压栈和退栈 。
六、继承同名成员处理方式
1、问题
- 问题:当子类和父类出现同名成员时,如何通过子类访问到子类和父类中的同名的数据那?
访问子类 同名成员时,直接访问 即可。访问父 类同名成员时,需加作用域 。
2.代码示例
# include <iostream>
using namespace std;
# include <string>
class Base {
public:
Base() {
m_A = 100;
};
void func() {
cout << "父类Base - func()调用。" <<endl;
};
void func(int a) {
cout<<"父类中的Base-func(int a)的重载"<<endl;
}
int m_A;
};
class Son :public Base {
public:
Son() {
m_A = 200;
}
void func() {
cout << "子类中的func()函数调用" << endl;
}
int m_A;
};
void test01() {
Son s1;
cout << "子类中的m_A = " << s1.m_A << endl;
cout << "父类中的m_A = " << s1.Base::m_A << endl;
};
void test02() {
Son s2;
s2.func();
s2.Base::func();
s2.Base::func(20);
};
int main() {
test02();
system("pause");
return 0;
}
3.小结
子类对象 可以直接访问 到子类 中的同名成员 。子类对象 加上作用域 可以访问父类 中的同名成员 。- 当子类与父类拥有同名的成员函数,
子类 会隐藏 掉父类 中所有同名成员函 数,加作用域可以访问 到父类中同名函数。
七、继承同名静态成员处理方式
1.问题
2.解决方法
-
静态成员和非静态成员出现同名,处理方式一致 -
访问子类同名成员 直接访问即可。 -
访问父类同名成员 需要加作用域。
3.静态成员变量特点
- 所有成员共享一份数据
- 编译阶段就开始分配内存。
- 类内声明,类外初始化。
4.静态的成员函数特点
- 静态的成员函数只能访问静态成员变量,不能访问非静态的成员变量。
- 所有对象共享同一份函数实例
5.代码示例
# include <iostream>
using namespace std;
# include <string>
class Base {
public:
static int m_A;
static void func()
{
cout << "Base-static void func()函数" << endl;
};
static void func(int a)
{
cout << "Base-static void func(int a)函数" << endl;
}
};
int Base::m_A = 100;
class Son :public Base {
public:
static int m_A;
static void func()
{
cout << "Son-static void func()函数" << endl;
}
};
int Son::m_A = 200;
void test01() {
cout << "通过对象访问:" << endl;
Son s;
cout << "Son 下的m_A"<<s.m_A << endl;
cout << "Base 下的m_A" << s.Base::m_A << endl;
cout << "通过类名访问:" << endl;
cout << "Son 下的m_A" <<Son::m_A<<endl;
cout << "Base 下的m_A " << Son::Base::m_A << endl;
}
void test02() {
cout <<"通过对象进行访问"<<endl;
Son s;
s.Base::func(20);
s.Base::func();
cout << "通过类名访问" << endl;
Son::func();
Son::Base::func();
};
int main() {
test02();
system("pause");
return 0;
}
6.小结
同名静态成员处理方式和非静态处理方式一样,只不过有两种访问的方式(通过对象,通过类名 )。
八、多继承语法
- C++允许
一个类继承多个类 相当于允许一个女号星任多个感跌。 - 语法:
class 子类:继承方式 父类1,继承方式 父类2... - 多继承可能会引发父类中有
同名成员出现 ,需要加作用域 进行区分 。 - 在实际开发中,不建议用多继承。
1.代码示例
# include <iostream>
using namespace std;
# include <string>
class Base1 {
public:
Base1() {
m_A = 10;
m_B = 10;
};
int m_A;
int m_B;
};
class Base2 {
public:
Base2()
{
m_B = 20;
m_A = 20;
}
int m_B;
int m_A;
};
class Son :public Base1, public Base2 {
public:
Son() {
m_C = 300;
m_D = 400;
};
int m_C;
int m_D;
};
void test02() {
Son s;
cout<<"sizeof Son = "<<sizeof(Son)<<endl;
cout<<"Base1中的m_A = "<<s.Base1::m_A<<endl;
cout <<"Base2中的m_A = "<<s.Base2::m_A<<endl;
}
int main() {
test02();
system("pause");
return 0;
}
九、棱形继承的问题以及解决办法
1.棱形继承的概念
- 两个派生类继承同一个基类
- 又有某个类同时继承两个派生类
- 这种继承被称为棱形继承,者是钻石继承
- 棱形继承的问题
1、羊继承了动物的数据,驼同样继承了动物的数据,当草泥马使用数据时,就会产生二义性。 2、草泥马继承自动物的数据继承了两份,其实我们应该清楚,这份数据我们只需要一份就可以,棱形继承导致数据有两份资源浪费。
2.代码示例
# include <iostream>
using namespace std;
#include <string>
class Animal {
public:
int m_Age;
};
class Sheep:public Animal {
};
class Tuo :public Animal {};
class SheepTuo :public Sheep, public Tuo {
};
void test01() {
SheepTuo st;
st.Sheep::m_Age = 100;
st.Tuo::m_Age = 200;
cout << "st.Sheep::m_Age" << st.Sheep::m_Age << endl;
cout << "st.Tuo::m_Age" <<st.Tuo::m_Age << endl;
};
int main() {
test01();
system("pause");
return 0;
};
3.棱形问题解决办法
# include <iostream>
using namespace std;
#include <string>
class Animal {
public:
int m_Age;
};
class Sheep:virtual public Animal {
};
class Tuo :virtual public Animal {};
class SheepTuo :public Sheep, public Tuo {
};
void test01() {
SheepTuo st;
st.Sheep::m_Age = 200;
st.Tuo::m_Age = 100;
cout << "st.Sheep::m_Age" << st.Sheep::m_Age << endl;
cout << "st.Tuo::m_Age" <<st.Tuo::m_Age << endl;
cout << st.m_Age << endl;
};
int main() {
test01();
system("pause");
return 0;
};
4.小结
棱形继承 带来的主要问题 是子类继承两份相同的数据,导致资源浪费 以及毫无意义。- 利用
虚继承解决 棱形继承问题。
总结
主要介绍了继承的语法,继承方式以及继承中相关问题的解决的方法。
|