C++学习04

一. 拷贝构造函数(重点)

1.系统会自动生成浅拷贝方法:

浅拷贝构造函数的条件:

使用一个对象去初始化另一个对象

2.自己重写拷贝构造函数方法

在构造函数传递一个参数是类的引用,那么这个构造函数就是重写之后的拷贝构造函数

语法:

C++
class 类名{
    public:
    //重写拷贝构造函数
    类名(类名 &a){
    }
}
//----------------------
class base{
    public:
    base(base &a){
    }
}

注意:

当用户自己重写拷贝构造函数之后,系统就不会再自动调用浅拷贝构造方法

C++
//重写拷贝构造函数 参数是 类的引用
base(base &a)
{
    cout << "这是我自己重写的拷贝构造函数" << endl;

    //初始化 (相当于是o1对象的成员的值 赋值给 o2对象的成员)
    this->x = a.x;
    this->y = a.y;

}

以上结果看起来和浅拷贝没有什么区别,那为什么不能浅拷贝,而要深拷贝????

举例:

C++
#include <iostream>
using namespace std;

extern "C"{
    #include <string.h>
}

class base{
    public:
    base(const char * str){
        //分配空间
        p = new char[100];
        //赋值字符串
        strcpy(p,str);
    }

    void show(){
        cout << "堆空间的地址:" <<(void *) p << endl;
        cout << "内容" << p << endl;
    }

    char * p;
};

int main(int argc, char const *argv[])
{
    base a("hello~");
    a.show();

    //用a对象初始化对象b -- 自动调用系统浅拷贝构造方法
    base b = a;
    b.show();

    //成员中如果有指针类型
    //因为浅拷贝是直接复制赋值
    //两个对象中的指针指向相同地址 内容也相同
    //导致修改一个对象的内容,另一个对象也会发生改变

    cout << "------修改b,输出a------" << endl;
    //修改b中p的内容
    strcpy(b.p,"world~");
    //输出a的内容,发现 也发生了改变
    a.show();
    return 0;
}

所以需要重写拷贝构造函数

练习深拷贝:

C++
#include <iostream>
using namespace std;

extern "C"{
    #include <string.h>
}

class new_base{
    public:
    new_base(const char * str,int size): size(size){
        p = new char[size];
        strcpy(p,str);
    }

    new_base(new_base &a){
        //初始化size
        this->size = a.size;
        //分配内存
        p = new char[this->size];
        //拷贝指针指向的内容
        strcpy(p,a.p);

    }
    void show(){
        cout << "地址" << (void *) p << endl;
        cout << "内容" <<  p << endl;
    }
    //显示接口
    private:
    char * p;  //指向堆空间的指针
    int size;  //分配堆空间的大小
};

int main(){
    //定义对象
    new_base a("哈哈哈",100);
    a.show();
    //调用深拷贝
    new_base b = a;
    b.show();

}

总结:如果对象中数据成员里有指针类型,必须自己重写拷贝构造函数(深拷贝)

二.类外定义类中成员函数(接口)

语法:

返回值类型 类名::函数名(参数){

    

}

举例:

C++
class base{
    public :
        //类内--函数声明
        void show();
}
//类外--函数定义
int base::show(int a){
    cout << a << endl;
    return a;
}

三.类的继承

继承作用:

  1. 提高代码的复用性
  1. 有利于软件版本的升级

继承定义:

从父类中获取一些数据成员或函数接口, 如果该成员是共有的或者受保护成员,则子类可以直接访问,提高代码的复用性

C++
class Person{
    public :
    int id;  //身份证号码
    char * name[40];  //名字
    double money; //资产
}
//不继承 代码重复编写
class stu{
    private:
    int grade;
}
//不继承 代码重复编写
class teacher{
    public :
    int id;  //身份证号码
    char * name[40];  //名字
    double money; //资产
    
    private:
    char * sick[1024];
}
A: 人脸数据采集  功能
A ---->  嘎了 走了
B: 人脸数据模型训练  继承 A
C: 人脸识别   继承A

继承语法:

C++
class  子类名: 继承方式 基类名
{
    //添加派生类的成员(子类成员)
}

C++
//定义person基类
class person{
    public:
    int age;
    double money;
};

//定义一个singer派生类
class singer:public person{
    //新增singer的数据
    private:
        int songs;
        int concerts;

};

父类 也叫基类

子类 也叫派生类

总结:

  • 派生类中能直接访问基类中的公有成员和保护成员
  • 如果派生类想要访问基类中私有成员,只能在基类中设置接口让派生类访问

四.继承

1. 语法:

C++
class 类名:继承方式 基类名{
    //派生类自己的成员
}

class son:public father{
    //son的成员
}

父类--基类

子类--派生类

2. 继承访问权限的问题:

  • 派生类继承基类后,可以访问基类中的受保护成员和公有成员
  • 如果想要访问基类中的私有成员,只能在基类中设计接口,让派生类来间接访问
  • 类外函数,只能访问基类和派生类中的公有成员

3. 继承方式:影响的是类外函数对基类成员的访问权限

  • public: 公有形式:  在派生类中保持基类原有的数据成员的访问权限(类外依然可以访问公有成员--常用)
  • private:私有形式:在派生类中将基类访问权限全部改为private私有(只有类内可以访问,类外都无法访问--偶尔用于细节控制)
  • protected:保护形式:在派生类中将基类中public公有变为protected保护成员(类外无法访问--基本不用)

练习:分析访问权限

C++
class base{
public:
    int a;
    int get_c(){
    return c;
    }
protected:
    int b;
private:
    int c
}

class new_base:public base{
public:
    void set(int a,int b){
        this->b = a+this->get_c();
        this->a = b++;
    }
}
//类外无法访问 保护成员b 私有成员c
void test(base &a){
    a.b = 10;
    a.c = 20;
}

4. 给基类成员初始化

派生类中使用初始化列表 给基类进行初始化

C++
class base{
public:
        base(int a,int b):a(a),b(b){
            cout << "初始化成功:" << a << "----" << b << endl;
        }
    
private:
    int a;
    int b;
};
//派生类
class new_base:public base{
    public:
    //利用参数列表 a1和b1是参数
    // 直接将基类中的成员a b放到初始化列表中---不可以(和ab的访问权限没关系)
    // new_base(int a1,int b1):a(a1),b(b1){}
    //将a1和b1传入到base基类中
    new_base(int a1,int b1):base(a1,b1){}
};

练习:利用初始化参数列表 去初始化基类私有成员 并定义输出接口

C++
struct Node{
    int m;
};
class base{

private :
    char str[100];
    struct Node node;
}

5.基类和派生类的构造函数

C++
#include <iostream>
using namespace std;

class base{
public:
    base(){
        cout << "调用base基类的无参构造函数" << endl;
    }
    base(int n):n(n){
        cout << "调用base基类的带参构造函数" << ":" << this->n << endl;

    }
private:
    int n;
};

class new_base:public base{
public:
    new_base(){
        cout << "调用new_base派生类的无参构造函数" << endl;
    }
    new_base(int m):base(m){
        cout << "调用new_base派生类的带参构造函数" << ":"<< m << endl;
    }
};

int main(int argc, char const *argv[])
{
    // base a;
    //定义派生类对象时 先调用基类的构造函数 再调用派生类的构造函数
    // new_base b;
    new_base b(10086);
    return 0;
}

6.基类和派生类的析构函数

C++
#include <iostream>
using namespace std;

class base{
public:
    ~base(){
        //再释放基类中成员空间
        cout << "调用基类base中的析构函数" << endl;
    }
};

class new_base : public base{
public:
    ~new_base(){
        //先释放派生类中成员空间
        cout << "调用派生类new_base中的析构函数" << endl;
    }
};

int main(int argc, char const *argv[])
{
   new_base obj;
    return 0;
}

总结:

构造函数:

执行顺序先调用基类的构造函数,再调用派生类的构造函数

析构函数:

执行顺序先调用派生类的析构函数,再调用基类的析构函数

注意: 想要派生类创建对象成功,一定要能够调用到基类和派生类的构造函数!!!!

目录

一. 拷贝构造函数(重点)

1.系统会自动生成浅拷贝方法:

2.自己重写拷贝构造函数方法

二.类外定义类中成员函数(接口)

三.类的继承

四.继承

1. 语法:

2. 继承访问权限的问题:

3. 继承方式:影响的是类外函数对基类成员的访问权限

4. 给基类成员初始化

5.基类和派生类的构造函数

6.基类和派生类的析构函数


评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值