提示:文章写完后,目录可以自动生成,如何生成可参考右边的帮助文档
文章目录
前言
提示:以下是本篇文章正文内容,下面案例可供参考
一、 继承
1.继承基本语法
class 子类(派生类):继承方式(pubilc private protected)父类(基类)
2.三种继承方式
#include<iostream>
using namespace std;
#include<string>
class Base
{
public:
Base(/* args */);
~Base();
int m_a;
protected:
int m_b;
private:
int m_c;
/* data */
};
Base::Base(/* args */)
{
}
Base::~Base()
{
}
class SubClass1 : public Base
{
private:
/* data */
public:
SubClass1(/* args */);
~SubClass1();
void print() {
m_a = 100; //public 成员变量 以 pubilc 方式继承,权限不变,类外可以访问
m_b = 100; //protected 成员变量 以 pubilc 方式继承,权限不变,类外不可以访问
// m_c = 100; //私有成员不可访问
}
};
SubClass1::SubClass1(/* args */)
{
}
SubClass1::~SubClass1()
{
}
class SubClass2 : protected Base
{
private:
/* data */
public:
SubClass2(/* args */);
~SubClass2();
void print() {
m_a = 100; //public 成员变量 以 protected 方式继承,权限变为protected,类不可以访问
m_b = 100; //protected 成员变量 以 protected 方式继承,权限不变,类外可以访问
// m_c = 100; //私有成员不可访问
}
};
SubClass2::SubClass2(/* args */)
{
}
SubClass2::~SubClass2()
{
}
class SubClass3 : private Base
{
private:
/* data */
public:
SubClass3(/* args */);
~SubClass3();
void print() {
m_a = 100; //public 成员变量 以 private 方式继承,权限变为private,类外不可以访问
m_b = 100; //protected 成员变量 以 private 方式继承,权权限变为private,类外不可以访问
// m_c = 100; //私有成员不可访问
}
};
SubClass3::SubClass3(/* args */)
{
}
SubClass3::~SubClass3()
{
}
void test01() {
SubClass1 test;
cout << test.m_a << endl;
// test.m_b = 100;
}
void test02() {
SubClass2 test;
// cout << test.m_a << endl;
// test.m_b = 100;
}
void test03() {
SubClass3 test;
// cout << test.m_a << endl;
// test.m_b = 100;
}
int main()
{
}
3,继承对象模型
子类继承父类的私有成员,不能访问但是继承了,可以通过sizeof打印出来
4.构造和析构顺序
可以通过在析构和构造函数中加打印来查看
base 的构造函数
SubClass1 的构造函数
SubClass1 的析构函数
base 的析构函数
5.继承中同名处理方式
子类中访问父类的同名对象,需要加父类的作用域
void test01() {
SubClass1 test;
//访问子类
cout << test.num << endl;
//访问父类中同名的成员
cout << test.Base::num << endl;
}
如果子类中出现了和父类名称相同的成员函数,子类的同名成员会隐藏掉父类中所有同名成员函数
如果想访问到父类中同名成员函数,需要加作用域
6.多继承语法
语法:
class 类名: 继承方式 父类1 , 继承方式 父类2:
容易引起,二义性,因为继承的父类可以,可能会存在相同的变量或者是函数名称,需要加作用域用来区别
菱形继承问题描述:
grandson 同时继承两个son父类的数据,就有两份的base的成员
可以用虚继承的方式来解决这个问题:
#include<iostream>
using namespace std;
#include<string>
class Base
{
public:
Base(/* args */);
~Base();
int num;
};
Base::Base(/* args */)
{
num = 100;
cout << "base 的构造函数" << endl;
}
Base::~Base()
{
cout << "base 的析构函数" << endl;
}
class Son1 :virtual public Base
{
private:
/* data */
public:
Son1(/* args */);
~Son1();
};
Son1::Son1(/* args */)
{
}
Son1::~Son1()
{
}
/*虚继承*/
class Son2 :virtual public Base
{
private:
/* data */
public:
Son2(/* args */);
~Son2();
};
Son2::Son2(/* args */)
{
}
Son2::~Son2()
{
}
class grandson : public Son1,public Son2
{
private:
/* data */
public:
grandson(/* args */);
~grandson();
};
grandson::grandson(/* args */)
{
}
grandson::~grandson()
{
}
void test()
{
grandson test;
test.Son1::num = 18;
test.Son2::num = 28;
/*增加虚继承之后可以发现继承的num是同一份,并且grandson这个类可以直接访问num*/
cout << test.Son1::num << endl;
cout << test.Son2::num << endl;
cout << test.num << endl;
}
int main()
{
test();
}
原理是:
一、派生类生成过程
1.吸收基类成员
处理构造函数和析构函数,其他所有东西度继承过来。
2.改造基类成员
隐藏:派生类成员函数名与基类相同,则会调用派生类函数。外层标识符在内层不可见。
3.添加新的成员
包括数据成员和成员函数。
二、派生类
1.构造函数执行过程
(1)传参
(2)先执行基类构造函数
(3)按照数据成员声明的顺序,开辟空间
(4)执行函数体。
注意:
在派生类调用基类构造函数,向基类函数传参,在基类函数的初始化列表中,以匿名对象的方式向基类带参构造函数传参。
2.构造函数执行过程
触发了类型兼容规则:需要基类对象的任何地方,都可以使用公有派生的对象来替代。
3.析构函数执行过程
(1)按照数据成员声明的逆序,释放空间
(2)先执行基类析构函数
三、访问权限控制
在继承的时候三个关键字,private,protected,public
由三种访问方式:基函数类内,派生函数类内,类外。
默认方式为:私有继承。
(1)继承方式为public,
基类数据类型为public,继承变为public
数类内可以访问,派生函数类内可以访问,类外可以访问
基类数据类型为protected,继承变为protected
数类内可以访问,派生函数类内可以访问,类外不能访问
基类数据类型为private,不可访问
数类内可以访问,派生函数类内不能访问,类外不能访问
(2)继承方式为protected
基类数据类型为public,继承变为protected
数类内可以访问,派生函数类内可以访问,类外不能访问
基类数据类型为protected,继承变为protected
数类内可以访问,派生函数类内可以访问,类外不能访问
基类数据类型为private,不可访问
(3)继承方式为private
基类数据类型为public,继承变为private
数类内可以访问,派生函数类内可以访问,类外不能访问
基类数据类型为protected,继承变为private
数类内可以访问,派生函数类内可以访问,类外不能访问
基类数据类型为private,不可访问
数类内可以访问,派生函数类内不能访问,类外不能访问
四、类型兼容性规则
在需要基类型对象的任何地方,都可以使用公有派生的对象。
有三种应用场景:(继承方式必须时public)
(1)创建对象时可以使用派生类对象。
(2)创建对象指针时可以使用派生类取地址。
(3)创建对象的引用时可以使用派生类对象。
五、qt
qt框架中,用于对象之间通讯的的信号与槽。