(C++面向对象的三大特性之一)
优点:减少大量的重复代码,提高效率
一.基本概念
1.语法:class 子类:继承方式 父类
(子类也称为派生类,父类也称为基类)
2.派类(子类)中的成员:
a.从基类中继承过来的(共性)
b.自己新添加的成员(个性)
3.继承方式:
//继承的方式:
class A//父类
{
public:
int a;
protected:
int b;
private:
int c;
};
a.公共继承:(类内,类外都可以访问)
//公共继承
class B :public A
{
public:
int a;//可访问
protected:
int b;//可访问
private:
int c;//不可以访问
};
b.保护继承:(类内可以访问,类外不能访问)
//保护继承(保护权限只能子类访问,类外访问不到)
class B :protected A
{
protected:
int a;//可以访问
int b;//可以访问
int c;//不可以进行访问
};
c.私有继承:(类内可以访问,类外不可以访问)
//私有继承
class B :private A
{
private:
int a;//可以访问
int b;//可以访问
int c;//不可以访问
};
总结:私有成员即使用公共继承法继承,也无法访问,类外均无法访问
二.继承中的对象模型
//继承中的对象模型
#include <iostream>
using namespace std;
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 << "size of Son=" << sizeof(Son) << endl;
}
int main()
{
test01();
return 0;
}
法1:(计算sz值)
运行结果:
----->父类中所有非静态成员属性都会被子类继承下去,父类中私有成员属性是被编译器隐藏了, 因此访问不到,但是确确实实被继承下去了。
法2(利用开发人员命令提示工具)
三.继承中构造和析构的顺序
--->子类继承父类后,当创建子类对象时,也会调用父类的析构函数
//继承中构造和析构的顺序
#include <iostream>
using namespace std;
class Base
{
public:
Base()
{
cout << "Base构造函数的调用" << endl;
}
~Base()
{
cout << "Base析构函数的调用" << endl;
}
};
class Son :public Base//公共继承
{
public:
Son()
{
cout << "Son构造函数的调用" << endl;
}
~Son()
{
cout << "Son析构函数的调用" << endl;
}
};
void test02()
{
Son s;
}
int main()
{
test02();
return 0;
}
运行结果:
先构造父类,再构造子类,析构与构造顺序相反
四.继承同名成员处理方式
(1).
//继承同名成员处理方式
#include <iostream>
using namespace std;
class Base
{
public:
Base()
{
m_A = 100;
}
int m_A;
};
class Son :public Base
{
public:
Son()
{
m_A = 200;
}
int m_A;
};
void test03()
{
Son s;
cout << s.m_A << endl;//访问子类中的成员
cout << s.Base::m_A << endl;//访问父类中的成员(加作用域)
}
int main()
{
test03();
return 0;
}
(2).
#include <iostream>
using namespace std;
class Base
{
public:
void func()
{
cout << "Base-func()函数的调用" << endl;
}
void func(int a)
{
cout << "Base-func()有参函数的调用" << endl;
}
};
class Son :public Base
{
public:
void func()
{
cout << "Son-func()函数的调用" << endl;
}
};
void test04()
{
Son s;
s.func();//子类
s.Base::func();//父类(加作用域)
s.Base::func(10);
}
int main()
{
test04();
return 0;
}
五.继承同名静态成员处理方式
静态成员变量:类内声明,类外初始化
//继承同名静态成员处理方式
//法1:通过对象访问
#include <iostream>
using namespace std;
class Base
{
public:
static int m_A;
};
int Base::m_A = 100;
class Son :public Base
{
public:
static int m_A;
};
int Son::m_A = 200;
void test05()
{
Son s;
cout << s.m_A << endl;//子类(200)
cout << s.Base::m_A << endl;//父类(100)
}
int main()
{
test05();
return 0;
}
//法2:通过类名访问
#include <iostream>
using namespace std;
class Base
{
public:
static int m_A;
};
int Base::m_A = 100;
class Son :public Base
{
public:
static int m_A;
};
int Son::m_A = 200;
void test05()
{
//Son s;
//cout << s.m_A << endl;//子类(200)
//cout << s.Base::m_A << endl;//父类(100)
cout << Son::m_A << endl;//子类
cout << Son::Base::m_A << endl;//父类
}
int main()
{
test05();
return 0;
}
静态成员变量不属于类的对象上,故可以用类名进行访问,
只有非静态成员变量属于类的对象上。
六.同名静态成员函数
#include <iostream>
using namespace std;
class Base
{
public:
static void func()
{
cout << "Base" << endl;
}
};
class Son :public Base
{
public:
static void func()
{
cout << "Son" << endl;
}
};
void test06()
{
Son::func();//子类
Son::Base::func();//父类
}
int main()
{
test06();
return 0;
}
七.多继承语法
--->允许一个类继承多个类,需要加作用域区分
---->语法:class 子类:继承方式父1,继承方式父2……
(C++实际开发中,不建议使用多继承)
//多继承语法
#include <iostream>
using namespace std;
class Base1
{
public:
Base1()
{
m_A = 100;
}
int m_A;
};
class Base2
{
public:
Base2()
{
m_B = 200;
}
int m_B;
};
class Son :public Base1, public Base2
{
public:
Son()
{
m_C = 300;
m_D = 400;
}
int m_C;
int m_D;
};
void test07()
{
Son s;
cout << sizeof(s) << endl;
}
int main()
{
test07();
return 0;
}
//运行结果:16
八.菱形继承(钻石继承)
//菱形继承
#include <iostream>
using namespace std;
class Animal//父类(虚基类)
{
public:
Animal()
{
m_Age = 18;
}
int m_Age;
};
class Sheep :virtual public Animal//子类1
{
};
class Tuo :virtual public Animal//子类2
{
};
class SheepTuo :public Sheep, public Tuo//同时继承两个子类
{
};
void test08()
{
SheepTuo st;
st.Sheep::m_Age = 21;
st.Tuo::m_Age = 22;
cout << st.Sheep::m_Age << endl;
cout << st.Tuo::m_Age << endl;
}
int main()
{
test08();
return 0;
}
运行结果:
----->在继承前在virtual使得共用一份数据(即m-Age),m-Age最后的值修改为什么,最后打印出来的值就为最后修改的那个值,只有一份m-Age,不会出现二义性
----->使用开发人员命令提示工具进行查看