C++学习笔记(二)

has_a关系:包括关系(复合关系,组合关系)

c 复制代码
has_a概念:
--------------------
has_a就是一个类型,
由其它多个类型的属性共同组合而成的类型,
形成了一个类与类的包含的关系。
--------------------------------------------
has_a中的构造与析构顺序:
----------------------------------
构造顺序:由内而外,按照声明顺序依次构造。
------------------------------------------------------
析构顺序:由外而内,按照声明逆序依次析构。

use a关系:友元关系

c 复制代码
描述类与函数,类与类之间的一种亲密关系。
-----------------------
友元函数:
----------------
在类中使用friend关键声明一个类外的函数为本类的友元函数.
--------------------------
友元函数的特性是:
---------------------------
当友元函数中有相应的类型的对象时,不受访问权限的影响。
-----------------------
#include <iostream>
using namespace std;
class Boy
{
private:
    int money;
public:
    Boy(int money)
    {
        this->money = money;
    }
    //在类中使用friend关键字修饰一下,声明外部的某个函数为本类的友元函数:
    friend void xiangqing(Boy& boy);
};
//友元函数中出现了类对象或引用对象或指针时,
//在调用其内部私有属性时,是不受访问权限的修饰的影响的。
void xiangqing(Boy& boy)
{
    cout << boy.money << endl;
}
int main()
{
    Boy boy(1000000);
    xiangqing(boy);
    return 0;
}
----------------------------------------
友元类:
------------
两个类之间的一种亲密关系。
------------------
在类中使用friend关键字友元一个类型 friend class xxx;
------------------------------
友元中注意事项:
-----------------------
A是B的友元,B是C的友元,但是A与C之间不一定是友元关系。

友元关系必须是直接关系,不存在间接传导关系。
-------------------------------------------
分文件编程的方式实现互相友元的方式:
----------------------------------------------
boy.h
------------
#ifndef BOY_H
#define BOY_H

#include <iostream>
#include <cstring>

using namespace std;

//前置声明
class Girl;

//类的声明
class Boy
{
private:
    string name;
    int age;
public:
    //构造声明
    Boy(string name,int age);
    //成员函数的声明
    void hardworking(Girl& girl);
    friend class Girl;
};


#endif // BOY_H



--------------
girl.h
---------------
#ifndef GIRL_H
#define GIRL_H

#include <iostream>
#include <cstring>

using namespace std;

class Boy;
class Girl
{
private:
    string name;
    int age;
public:
    Girl(string name,int age);
    void shopping(Boy& boy);
    friend class Boy;
};





#endif // GIRL_H



--------------
boy.cpp
-------------------
#include "boy.h"
#include "girl.h"


Boy::Boy(string name,int age)
{
    this->name = name;
    this->age = age;

}

void Boy::hardworking(Girl &girl)
{
    cout << girl.name << "和" << this->name <<endl;
}



----------------------
girl.cpp
----------------------
#include "girl.h"

#include "boy.h"


Girl::Girl(string name,int age)
{
    this->name = name;
    this->age = age;

}

void Girl::shopping(Boy &boy)
{
    cout << boy.name << "与" << this->name <<endl;
}




-----------------------
main.cpp
-----------------------
#include "boy.h"
#include "girl.h"

int main()
{
    Boy b1("kk",26);
    Girl g1("dd",25);

    b1.hardworking(g1);
    g1.shopping(b1);
    return 0;
}



----------------------

is_a关系 (继承关系)

c 复制代码
继承关系的用意和目的是什么?
------------------------------------------
提高代码复用性与拓展性
--------------------------------
首先要把这一类的事件进行抽象出来一些共有的属性与特征,

把它们定义为父类。

然后,再用这个父类,对具有不同特点的子类进行派生。

这样就可以派生出各种不同的子类。

子类不仅拥有父类的共有的特性,与具备子类独用的特性。

这样的代码的复用性与拓展性就会非常灵活。
-----------------------------
注意:
---------
继承关系中,子类并不继承父类中的构造函数。

因为构造函数是特别的为本类域进行初始化的函数,

并不会被继承。

子类中要有子类的默认构造或自定义有参构造
------------------------------------------------------
继承关系的语法形式:
-------------------------
单继承:
---------
class 子类 : 继承权限 + 父类
{
    //单继承的语法形式:
    //继承即是子类继承了父类中的所有属性与方法(构造函数除外)
};
----------------------------
继承关系中的子类有自己的构造不会继承父类的构造!
-------------------------------------------------------------
多继承:
-------------
class 子类 : 继承权限1,父类1,继承权限2,父类2,... 继承权限n,父类n
{
    //多重继承的语法:
    //子类继承多个父类中的所有属性与方法。
};
----------------------------------------------------------
多继承一般不推荐使用,在公司做开发,能使用单继承不使多继承,
如果使用多继承那么就是继承多个抽象类。
--------------------------------------------------
三类访问权限:
-------------------
public的变量和函数在类的内部外部都可以访问。

protected的变量和函数只能在类的内部和其派生类中访问。

private修饰的元素只能在类内访问。
---------------------------------------------
权限访问范围问题分为三类:
------------------------------------
本类可访问
子类可访问(传递性,即这个成员可以在子类存在,可被继承)
外界可访问(对外性,即可通过类对象访问)
----------------------------------------------
public成员       具有对外性和传递性(即其可被子类继承)。

protected成员 具有传递性。

private成员      失去了其两者性质。
---------------------------------------------------
继承权限:
--------------
通过继承,我们可以修改并继承父类成员,
但首先要满足的条件:父类成员具有传递性。
这也是为什么private成员在子类中不可见的原因,因为它失去了传递性。
-------------------------------------------------
简单叙述一下:三种继承方式就相当于,在子类中给父类成员统一分配一个访问权限。
-------------------------------------------------
重点理解以下两句:
--------------------------
1.基类的成员访问权限决定了派生类中该成员访问权限的下限。
------------
 即我们不能为父类增添某些权限,
比如我们不能为父类private成员增加传递性来访问它
-----------------------------------------
2.对基类的继承权限可改变派生类中该成员访问权限的上限。
-------------------------------------------------
即我们可以减少父类成员的权限,
比如我们可以剪切父类public成员的对外性,使其无法再进行类成员访问。
------------------------------------------------------
单继承关系下的内存布局:
----------------------------------
构造顺序:
------------------
先调用父类中的构造完成对父类类域中的属性进行初始化,
然后调用子类的构造完成对子域类域中特有属性的初始化。
-------------------------------------
析构顺序:
-----------
先析构子类,再析构父类。
--------------------------------------------
子类中与父类中的属性或方法的同名问题(自动隐藏机制)
----------------------------------------------------------------
当子类中有与父类同名属性或函数时,
父类中的同名属性或函数将自动隐藏在自己的父类的类域之中,
如果想访问父类类域之中的属性或方法,
请使用域名::访问
-------------------------------
继承关系下的类型兼容规则:
is_a关系: 子类是一个父类的一个拓展
-------------------------------------------------
1.父类指针或引用可以天然且安全,
(无需进行类型转型的)
指向或引用子类类型的对象。
反之则不成立。
-----------------------------------------
当父类中没有有默认的构造时,
应该在子类的构造函数的初始化列表中进行指定。
父类指针只能调用子类类域中所包含的父类中的类域中的方法或属性。
------------------------------------
所以也存在一个问题:
如果使用父类指针在释放资源时,请注意要强转成子类指针才可以完全释放,
不然就泄漏了。
------------------------------
    Car* car = new BMW(500);
    delete (BMW*)car;
---------------------------------------
多继承与棱形继承:
-----------------------
class 子类 : 继承权限1 父类1,继承权限2,父类2,... 继承权限n,父类n
{
    //多重继承的语法:
    //子类继承多个父类中的所有属性与方法。
};
----------------------
在多继承时,虽然多继承可以大在提高代码的复用性,
但也往往带着无法解决的问题:代码冗余,当多个父类中有同名函数或属性时,
访问时,出现二义性的问题。
需要注意使用类域::访问的方式进行指定访问,
这样给程序设计带来很多不便,所以多继承在开发时尽量避免。
如果一定要使用多继承时,推荐使用多继承多个抽象类,
因为抽象类一般都没有具体的属性,只有纯虚函数。
------------------------------------------------------------
开发经验:
----------------------
在开发中,如果使用has_a与is_a关系都可以解决问题,优先has_a关系。

如果使用继承,能用单继承,不用多继承,

如果一定要使用多继承,请使用多继承多个抽象类。

坚决不用棱形继承。如果一定要用,请使用虚继承。
相关推荐
red_redemption22 分钟前
自由学习记录(214)
学习
疯狂打码的少年1 小时前
【数据结构】树的基本概念与二叉树定义
java·数据结构·笔记·算法
马上去吃汉堡王1 小时前
Windows11安装Geant4
笔记
气泡水。1 小时前
RHCSA笔记实记
linux·笔记
祈禾2 小时前
Redis三大特殊数据类型
运维·服务器·数据库·redis·笔记·缓存
祈禾2 小时前
计算机组成原理之编译、汇编、链接、解释
开发语言·汇编·笔记·学习
知识分享小能手2 小时前
线性代数学习教程,从入门到精通,矩阵的初等变换与线性方程组(6)
学习·线性代数·矩阵
小龙报3 小时前
【优选算法】1.搜索插入位置 2.x的平方根
java·c语言·数据结构·c++·python·算法·蓝桥杯
A_humble_scholar3 小时前
Linux(二) C++ TCP/UDP网络编程
linux·网络·c++
我命由我123453 小时前
四流一致(合同流、业务流、资金流、发票流)
经验分享·学习·职场和发展·求职招聘·职场发展·产品经理·学习方法