当前位置: 首页 > news >正文

【C++】c++的继承

目录

思维导图大纲:

1.基类和派生类 

1.1 定义格式 

1.2 继承方式 

 1.3 基类和派生类的转换

 2. 继承中的作用域(隐藏关系)

2.1 考察继承作⽤域相关选择题

3. 派生类的默认成员函数

4. 继承类模板 

 5. 一个不能被继承的类

​编辑 6.继承与友元

​编辑 7. 继承与静态成员

​编辑 8. 继承类型

8.1 单继承 

8.2 多继承 

8.2.1 菱形继承 

二义性: 

数据冗余:

 8.3 多继承中的指针偏移问题

9. 继承和组合 

继承:is-a 

组合:has-a 


思维导图大纲:

1.基类和派生类 

基类和派生类又可以称作父类和子类,派生类可以继承基类中的成员,并且还可以拥有自己的成员,就好比植物是一个大类,而蒲公英也是一种植物拥有植物的特性(也就是植物类的成员属性),同时蒲公英也拥有自己的其他特点,如传播种子的方式;所以基类和派生类的关系如下图:

1.1 定义格式 

1.2 继承方式 

我们之前学习过每个类域都有着不同的成员,如public,protected,private。对于公共的成员public不管是类域内还是外都可以访问,对于后面两者只有在类域才可以访问,同样的是基类和派生类之间的基础方式也存在这种关系!

  •  由上图可知基类的不同成员和继承方式,会选取权限小的一方继承给派生类
  •  基类成员不希望外部访问,只希望派生类访问,因此出现了protected成员

  • 如果是基类的private成员无论以什么方式继承给派生类成员,在派生类中我们都不可见,语法上也不可以访问,但是基类的private成员确实继承给了派生类!
  • class默认为private继承,struct默认为public继承!
// 人->学生
class Person
{
public:
protected:string _name = "欧阳";int _age = 20;string gender = "男";
private:int _hide = 1;
};class Student : public Person // public 继承方式
{
public:void Print() const{cout << _name << endl;cout << _age << endl;cout << gender << endl;cout << _id << endl;/*cout << Person::_hide << endl; */  // err}
protected:string _id = "001";
};int main()
{Student s;s.Print();return 0;
}

 

 1.3 基类和派生类的转换

由之前我们可以得知派生类会继承基类的成员,所以我们可以将派生类的对象赋值给基类对象,实现这种操作的关键是切片操作!编译器会将派生类对象中与基类对象重合的成员切出来赋值给基类对象 ,但是基类对象不可以赋值给派生类对象,因为基类对象不含有派生类对象的部分成员!基类的指针和引用可以指向派生类对象

// 人->学生
class Person
{
public:
protected:string _name = "欧阳";int _age = 20;string gender = "男";
};class Student : public Person // public 继承方式
{
public:
protected:string _id = "001";
};int main()
{Person p;  // 基类对象Student s; // 派生类对象p = s;     // 派生类对象->基类对象//s = p;     // errPerson* ptr1 = &s; // 指针Person& ptr2 = s;  // 引用return 0;
}

 2. 继承中的作用域(隐藏关系)

我们都知道基类和派生类属于两个类,因此他们拥有不同的类域,但是如果基类和派生类直接存在相同的变量或者函数时,会发生什么呢?

class A
{
public:
protected:int _num = 999;
};class B : public A
{
public:void Print(){cout << _num << endl;}
protected:int _num = 111;
};int main()
{B b;b.Print();return 0;
}

以上代码b.Print()会打印什么呢?是打印基类A的_num,还是派生类B的_num。 

 为什么是111呢,其实这边基类的_num和派生类的_num构成了隐藏的关系,隐藏起了基类的成员,如果我们需要访问打印基类的成员需要指定类域

  • 注意的是如果是成员函数的隐藏,只需要函数名相同就构成隐藏
class A
{
public:
protected:int _num = 999;
};class B : public A
{
public:void Print(){cout << _num << endl;cout << A::_num << endl;}
protected:int _num = 111;
};int main()
{B b;b.Print();return 0;
}

2.1 考察继承作⽤域相关选择题

class A
{
public :void fun(){cout << "func()" << endl;}
};
class B : public A
{
public :void fun(int i){cout << "func(int i)" << i << endl;}
};
int main()
{B b;b.fun(10);b.fun();return 0;
};

  •  看问题一:

首先肯定不是重载关系,重载需要在同一作用域,函数名相同,参数类型,个数,顺序需要有一项不同,返回类型可以相同也可以不同!

A与B是继承的关系,根据前面基类和派生类中的函数只要函数名相同就构成隐藏关系

  • 看问题二:

由于构成了隐藏关系,所以b类中只存在 void fun(int i)函数,b.fun(10);的传参调用是正确的,但是b.fun();的函数调用是错误的!所以会编译报错

3. 派生类的默认成员函数

  •  派⽣类的构造函数必须调⽤基类的构造函数初始化基类的那⼀部分成员。如果基类没有默认的构造函数,则必须在派⽣类构造函数的初始化列表阶段显⽰调⽤
  • 派⽣类的拷⻉构造函数必须调⽤基类的拷⻉构造完成基类的拷⻉初始化。
  • 派⽣类的operator=必须要调⽤基类的operator=完成基类的复制。需要注意的是派⽣类的

    operator=隐藏了基类的operator=,所以显⽰调⽤基类的operator=,需要指定基类作⽤域

  • 派⽣类的析构函数会在被调⽤完成后⾃动调⽤基类的析构函数清理基类成员。因为这样才能保证派⽣类对象先清理派⽣类成员再清理基类成员的顺序。

  • 派⽣类对象初始化先调⽤基类构造再调派⽣类构造

  • 派⽣类对象析构清理先调⽤派⽣类析构再调基类的析构

class Person
{
public:Person(const char* name = "xxx"): _name(name){cout << "Person()" << endl;}Person(const Person& p): _name(p._name){cout << "Person(const Person& p)" << endl;}Person& operator=(const Person& p){cout << "Person operator=(const Person& p)" << endl;if (this != &p)_name = p._name;return *this;}~Person(){cout << "~Person()" << endl;}
protected:string _name; // 姓名
};class Student : public Person
{
public:Student(const char* name, int num, const char* addrss):Person(name),_num(num),_addrss(addrss){}// 严格说Student拷贝构造默认生成的就够用了// 如果有需要深拷贝的资源,才需要自己实现Student(const Student& s):Person(s),_num(s._num),_addrss(s._addrss){// 深拷贝}// 严格说Student赋值重载默认生成的就够用了// 如果有需要深拷贝的资源,才需要自己实现Student& operator=(const Student& s){if (this != &s){// 父类和子类的operator=构成隐藏关系Person::operator=(s);_num = s._num;_addrss = s._addrss;}return *this;}// 严格说Student析构默认生成的就够用了// 如果有需要显示释放的资源,才需要自己实现// 析构函数都会被特殊处理成destructor() ~Student(){// 子类的析构和父类析构函数也构成隐藏关系// 规定:不需要显示调用,子类析构函数之后,会自动调用父类析构// 这样保证析构顺序,先子后父,显示调用取决于实现的人,不能保证// 先子后父//Person::~Person();//delete _ptr;}
protected:int _num = 1; //学号string _addrss = "西安市高新区";int* _ptr = new int[10];
};int main()
{Student s1("张三", 1, "西安市");Student s2(s1);Student s3("李四", 2, "咸阳市");s1 = s3;/*Person* ptr = new Person;delete ptr;*/return 0;
}

4. 继承类模板 

// 继承类模板
#include <vector>
template<class T>
class Stack : public std::vector<T>
{
public:void Push(const T& x){push_back(x);}void Pop(){pop_back();}T& top(){return back();}bool empty(){return empty();}
};int main()
{Stack<int> st;st.Push(1);st.Push(2);st.Push(3);while (!st.empty()){cout << st.top() << endl;st.Pop();}return 0;
}

我们编译以上代码会报错!

 这是为什么呢?首先我们是一个模板,我们使用Stack模板创建了st这个对象,但是在调用函数时会涉及到vector<int>,这时我们不仅实例化Stack<int>,也实例化vector<int>但是模板是需要按需实例化,所以push_back等函数并没有实例化,就会产生报错,我们在使用继承类模板时需要注意

  • 基类是类模板时,需要指定⼀下类域,
  • 否则编译报错:error C3861: “push_back”: 找不到标识符
  • 因为stack<int>实例化时,也实例化vector<int>了
  • 但是模版是按需实例化,push_back等成员函数未实例化,所以找不到
// 继承类模板
#include <vector>
template<class T>
class Stack : public std::vector<T>
{
public:void Push(const T& x){vector<T>::push_back(x);}void Pop(){vector<T>::pop_back();}T& top(){return vector<T>::back();}bool empty(){return vector<T>::empty();}
};int main()
{Stack<int> st;st.Push(1);st.Push(2);st.Push(3);while (!st.empty()){cout << st.top() << " ";st.Pop();}return 0;
}

 5. 一个不能被继承的类

需要使用关键字final

class A final
{
public:
};class B : public A
{
public:
};int main()
{B b;return 0;
}

 6.继承与友元

派生类继承基类,但是基类中的友元函数不可以被派生类继承 

class Student;
class Person
{
public :friend void Display(const Person& p, const Student& s);
protected:string _name; // 姓名
};
class Student : public Person
{
protected :int _stuNum; // 学号
};
void Display(const Person& p, const Student& s)
{cout << p._name << endl;cout << s._stuNum << endl;
} int main()
{Person p;Student s;// 编译报错:error C2248: “Student::_stuNum”: ⽆法访问 protected 成员// 解决⽅案:Display也变成Student 的友元即可Display(p, s);return 0;
}

 7. 继承与静态成员

派生类继承基类的非静态成员,都会额外开空间进行存储,但是对于静态成员有且只有一个,无论存在多少派生类 

class Person
{
public :string _name;static int _count;
};int Person::_count = 0;class Student : public Person
{
protected :int _stuNum;
};int main()
{Person p;Student s;// 这⾥的运⾏结果可以看到⾮静态成员_name的地址是不⼀样的// 说明派⽣类继承下来了,⽗派⽣类对象各有⼀份cout << &p._name << endl;cout << &s._name << endl;// 这⾥的运⾏结果可以看到静态成员_count的地址是⼀样的// 说明派⽣类和基类共⽤同⼀份静态成员cout << &p._count << endl;cout << &s._count << endl;// 公有的情况下,⽗派⽣类指定类域都可以访问静态成员cout << Person::_count << endl;cout << Student::_count << endl;return 0;
}

 8. 继承类型

8.1 单继承 

 

8.2 多继承 

8.2.1 菱形继承 

 菱形继承会带来两项问题:

  • 二义性
  • 数据冗余
二义性: 
class Person
{
protected:string _name;string _gender;int _age;
};class Student : public Person
{
protected:int _StuNum;
};class Teacher : public Person
{
protected:int _id;
};class Total : public Student, public Teacher
{
protected:string _data;
};int main()
{Total tl;tl._name = "欧阳"; // 二义性!return 0;
}

我们可以指定类域解决这种问题 

int main()
{Total tl;//tl._name = "欧阳";tl.Student::_name = "欧阳";tl.Teacher::_name = "ouyang";return 0;
}
数据冗余:

 需要使用虚继承virtual解决这种问题!

class Person
{
public:string _name;string _gender;int _age;
};class Student : virtual public Person
{
protected:int _StuNum;
};class Teacher : virtual public Person
{
protected:int _id;
};class Total : public Student, public Teacher
{
protected:string _data;
};int main()
{Total tl;//tl._name = "欧阳";tl.Student::_name = "欧阳";tl.Teacher::_name = "ouyang";return 0;
}

 

 8.3 多继承中的指针偏移问题

当一个派生类继承多个基类时,指向不同基类的顺序会根据继承顺序产生指针偏移的问题,偏移的大小为前一个基类的数据大小 

class Base1 { public: int _b1; };
class Base2 { public: int _b2; };
class Derive : public Base1, public Base2 { public: int _d; };
int main()
{Derive d;Base1* p1 = &d;Base2* p2 = &d;Derive* p3 = &d;cout << p1 << endl;cout << p2 << endl;cout << p3 << endl;return 0;
}

9. 继承和组合 

继承:is-a 

继承允许你根据基类的实现来定义派⽣类的实现。这种通过⽣成派⽣类的复⽤通常被称为⽩箱复⽤ (white-box reuse)。术语“⽩箱”是相对可视性⽽⾔:在继承⽅式中,基类的内部细节对派⽣类可 ⻅。继承⼀定程度破坏了基类的封装,基类的改变,对派⽣类有很⼤的影响。派⽣类和基类间的依赖关系很强,耦合度⾼。 

组合:has-a 

对象组合是类继承之外的另⼀种复⽤选择。新的更复杂的功能可以通过组装或组合对象来获得。对 象组合要求被组合的对象具有良好定义的接⼝。这种复⽤⻛格被称为⿊箱复⽤(black-box reuse),因为对象的内部细节是不可⻅的。对象只以“⿊箱”的形式出现。组合类之间没有很强的依赖关 系,耦合度低。优先使⽤对象组合有助于你保持每个类被封装。 

低耦合高内聚 

// 继承 is-a
class Stack1 : public std::vector<int>
{
};// 组合 has-a
class Stack2
{
protected:std::vector<int> _v;
};int main()
{return 0;
}

相关文章:

【C++】c++的继承

目录 思维导图大纲&#xff1a; 1.基类和派生类 1.1 定义格式 1.2 继承方式 1.3 基类和派生类的转换 2. 继承中的作用域(隐藏关系) 2.1 考察继承作⽤域相关选择题 3. 派生类的默认成员函数 4. 继承类模板 5. 一个不能被继承的类 ​编辑 6.继承与友元 ​编辑 7. 继…...

【ShuQiHere】 进制转换的世界:从十进制到二进制、十六进制的转换技巧

【ShuQiHere】 在计算机科学中&#xff0c;进制转换&#xff08;Radix Conversion&#xff09; 是一个基础且非常重要的技能。无论是理解计算机的存储、数据表示&#xff0c;还是在编程中处理不同的进制数据&#xff0c;进制转换都是不可或缺的。本文将详细讲解 十进制&#x…...

《化工管理》

《化工管理》征稿简则 《化工管理》杂志是由中国石油和化学工业联合会主管、中国化工企业管理协会主办&#xff0c;1986年创刊&#xff0c;在国内外公开发行&#xff0c;国内统一连续出版物号&#xff1a;CN 11—3991/F&#xff0c;中国标准连续出版物号&#xff1a;ISSN 1008—…...

LeetCode70:爬楼梯

class Solution { public:int climbStairs(int n) {if(n 1) return 1;if(n 2) return 2;vector<int> dp(n 1, 0);dp[1] 1;dp[2] 2;for(int i 3; i < n 1; i){dp[i] dp[i - 1] dp[i - 2];}return dp[n];} }; 这个题目也就是最简单的动态规划&#xff0c;题目…...

[程序员] 前人留下的苦难源,我们是否有勇气改正?

最近遇到一个客户现场发现的&#xff0c;表象是网络有问题&#xff0c;分析一圈下来发现是程序进入了某种死循环状态&#xff0c;耗尽CPU。 产品里的很多线程/进程的优先级设置的很高&#xff0c;甚至高过了内核运行程序的优先级&#xff0c;高过了产品内警告处理程序的运行&a…...

聚类_K均值

import numpy as np import matplotlib.pyplot as plt from sklearn.datasets import make_blobs1.数据预处理 #创建基于高斯分布的样本点, x是点的坐标&#xff0c;y是所属聚类值 x, y make_blobs(n_samples100, centers6, random_state100, cluster_std0.6) # 设置图形尺寸…...

Mac电脑剪切板在哪里找 苹果电脑剪切板打开教程【详解】

Windows 和 Mac 电脑在使用方式上存在一些差异&#xff0c;许多习惯了 Windows 系统的用户初次接触 Mac 时可能会对某些操作感到困惑。比如&#xff0c;很多人会问&#xff1a;Mac 上的剪贴板在哪里&#xff1f;如果你也有这样的疑问&#xff0c;不妨看看下面这篇关于如何在 Ma…...

Python编程 - 三器一包

目录 前言 一、迭代器 &#xff08;一&#xff09;基本概念 &#xff08;二&#xff09;迭代器和可迭代对象 &#xff08;三&#xff09;创建迭代器 &#xff08;四&#xff09;内置迭代器函数 &#xff08;五&#xff09;优点和局限性 二、生成器 &#xff08;一&…...

InternVL 多模态模型部署微调实践

友情链接 该文档参考InternVL垂直领域场景微调实践而写成&#xff0c;感谢社区同学法律人的文档。 写在前面&#xff08;什么是InternVL&#xff09; InternVL 是一种用于多模态任务的深度学习模型&#xff0c;旨在处理和理解多种类型的数据输入&#xff0c;如图像和文本。它…...

Ruby Dir 类和方法

Ruby Dir 类和方法 Ruby 中的 Dir 类提供了用于处理目录的各种方法。这些方法允许您列出目录内容、更改当前工作目录、创建和删除目录等。本文将详细介绍 Dir 类的常用方法&#xff0c;并通过示例展示如何使用它们。 目录 Dir 类的简介常用方法 Dir.chdirDir.childrenDir.de…...

C++STL~~deque

文章目录 deque的概念deque的使用deque的练习总结 deque的概念 deque(双端队列)&#xff1a;是一种序列容器、是一种双开口的"连续"空间的数据结构&#xff0c;双开口的含义是&#xff1a;可以在头尾两端进行插入和删除操作&#xff0c;且时间复杂度为O(1)&#xff…...

SpringCloud的学习,Consul服务注册与发现、分布式配置,以及 服务调用和负载均衡

介绍 Consul 是一套开源的分布式服务发现和配置管理系统&#xff0c;由 HashiCorp 公司用 Go 语言开发。 提供了微服务系统中的服务治理、配置中心、控制总线等功能。这些功能中的每一个都可以根据需要单独使用&#xff0c;也可以一起使用以构建全方位的服务网格&#xff0c;…...

闯关leetcode——26. Remove Duplicates from Sorted Array

大纲 题目地址内容 解题代码地址 题目 地址 https://leetcode.com/problems/remove-duplicates-from-sorted-array/description/ 内容 Given an integer array nums sorted in non-decreasing order, remove the duplicates in-place such that each unique element appear…...

基于A2C与超启发式的航天器星载自主任务规划算法-笔记

1. Actor-Critic 模块 主要文件&#xff1a;AC.py, PolicyNet.py, ValueNet.py作用&#xff1a;该模块实现了 A2C&#xff08;Advantage Actor-Critic&#xff09;强化学习算法。其中&#xff0c;ActorCritic 类是核心&#xff0c;它同时管理策略网络&#xff08;Actor&#x…...

[机器学习]决策树

1 决策树简介 2 信息熵 3 ID3决策树 3.1 决策树构建流程 3.2 决策树案例 4 C4.5决策树 5 CART决策树&#xff08;分类&回归&#xff09; 6 泰坦尼克号生存预测案例 import pandas as pd from sklearn.model_selection import train_test_split from sklearn.tree import …...

CentOS7更换阿里云yum更新源

目前CentOS内置的更新安装源经常报错无法更新&#xff0c;或者速度不够理想&#xff0c;这个时候更换国内的镜像源就是一个不错的选择。 备份内置更新源 mv /etc/yum.repos.d/CentOS-Base.repo /etc/yum.repos.d/CentOS-Base.repo.backup 下载阿里云repo源&#xff08;需要系统…...

算法参数对拥塞控制的影响

来看看参数对公平收敛的影响。仅假象一下就知道应该是个加权公平&#xff0c;但事实如何&#xff0c;还是要具体看一下。 首先看 aimd&#xff0c;标准的 reno 算法是每 round 之后 cwnd 加 1&#xff0c;但如果有些流加 1&#xff0c;有些流加 2&#xff0c;会如何&#xff1…...

Go websocket

Go 中的 gorilla/websocket 是一个常用且高效的 WebSocket 实现库&#xff0c;可以帮助你轻松地在 Web 应用中实现实时通信。学习 gorilla/websocket 的基本用法包括建立 WebSocket 连接、发送和接收消息、处理错误、以及在实际场景中的使用。以下是关于 gorilla/websocket 的学…...

C# 委托与事件 观察者模式

委托与事件是一种观察者模式。 什么是委托与事件 在c#中&#xff0c;委托类似于代理&#xff0c;也跟其它语言的函数指针、回调函数等相似&#xff0c;但委托是类型安全和可靠的。声明自定义委托时&#xff0c;加上delegate关键字&#xff0c;委托定义类似于接口。 事件是特殊…...

K8S - 用service account 登陆kubectl

刚安装好k8s时 我就可以用kubectl 在master server里管理k8s的资源。 这时我们是感觉不到 k8s的用户和权限管理存在的&#xff0c; 但是其实用户的配置都在kubeclt 的配置文件中 /etc/kubernetes/admin.conf 中 我们可以用下命令来查看当前正在用的帐号 rootk8s-master:~/.d…...

Redis 持久化机制详解

引言 Redis 是一款基于内存的高性能键值存储系统&#xff0c;为了在数据丢失时能快速恢复&#xff0c;Redis 提供了多种持久化机制。这些持久化机制可以将内存中的数据存储到磁盘上&#xff0c;确保即使系统重启或宕机后也能恢复数据。Redis 支持两种主要的持久化方式&#xf…...

小阿轩yx-案例:Zabbix监控kubernetes云原生环境

小阿轩yx-案例&#xff1a;Zabbix监控kubernetes云原生环境 前言 传统监控的本质 就是收集、分析和使用信息来观察一段时间内监控对象的运行进度&#xff0c;并且进行相应的决策管理的过程&#xff0c;监控侧重于观察特定指标。 随着云原生时代的到来 我们对监控的功能提出…...

量化交易的个人见解

程序化交易在国内兴起有些年数了&#xff0c;个人以为&#xff0c;程序化交易与量化投资的关系&#xff0c;在于两者侧重点有差别。程序化交易侧重于下单的动作是机器自动执行的&#xff0c;量化投资则侧重于投资分析的过程是通过一个量化模型来实现的&#xff0c;所以量化投资…...

Java集合(一)

目录 Java集合&#xff08;一&#xff09; 集合介绍 单列集合分类 Collection接口 创建Collection实现类对象 常用方法 迭代器 基本使用 迭代器的执行过程 迭代器底层原理 集合中的并发修改异常及原因分析 List接口 ArrayList类 介绍 常用方法 遍历集合 Array…...

车载软件架构 --- SOA设计与应用(下)

我是穿拖鞋的汉子,魔都中坚持长期主义的汽车电子工程师。 老规矩,分享一段喜欢的文字,避免自己成为高知识低文化的工程师: 屏蔽力是信息过载时代一个人的特殊竞争力,任何消耗你的人和事,多看一眼都是你的不对。非必要不费力证明自己,无利益不试图说服别人,是精神上的节…...

网络原理 IP协议与以太网协议

博主主页: 码农派大星. 数据结构专栏:Java数据结构 数据库专栏:MySQL数据库 JavaEE专栏:JavaEE 关注博主带你了解更多数据结构知识 目录 1.网络层 IP协议 1.IP协议格式 2.地址管理 2.1 IP地址 2.2 解决IP地址不够用的问题 2.3NAT网络地址转换 2.4网段划分 3.路由选择…...

k8s的安装

k8s的安装 1.创建主机&#xff0c;设置ip,hostname&#xff0c;关闭firewalld,selinux,NetworkManager 编号主机名称ip1k8s-master192.168.118.662k8s-node01192.168.118.773k8s-node02192.168.118.88 2.设置主机之间的ssh免密 [rootk8s-master ~]# ssh-keygen [rootk8s-ma…...

Qt中样式表常用的属性名称定义

Qt中&#xff0c;用好样式表&#xff0c;不但可以做出意想不到的酷炫效果&#xff0c;有时候也能减轻开发量&#xff0c;可能由于你不了解某些样式使用&#xff0c;想破脑袋通过代码实现的效果&#xff0c;反倒不如别人用样式&#xff0c;一两句样式脚本就搞定。 Qt中&#xff…...

React源码学习(一):如何学习React源码

本系列源码学习&#xff0c;是基于 v16.13.1&#xff0c;v17.x与v16.x区别并不太大&#xff01; 一、如何正确的学习React源码&#xff1f; 找到Github&#xff0c;转到React仓库&#xff0c;fork / clone源码&#xff1a;React 查看Readme&#xff0c;在Documentation中有Cont…...

云计算服务的底层,虚拟化技术的实现原理

虚拟化技术&#xff1a; 一、 从cpu说起&#xff0c; intel和amd等cpu制造商 为了提高其cpu对 虚拟化程序的运算速度&#xff0c; 给cpu硬件里面 增加了指令集 VMLAUNCH, VMRESUME, VMEXIT, VMXOFF 这些指令集称为硬件辅助虚拟化技术的指令集。 ---------------------…...