7、类型转换构造、析构、深拷贝、类的静态成员

2023-12-14 19:30:37

1、类型转换构造 |自定义转换

利用一个已定义的对象,来定义另一个不同类型的对象
实现从源类型到目标类型的隐式类型转换的目的

总结下已知构造,包括类型转换构造

如下,如果Person给Human赋值时,Person有私有变量,则需要在Person声明友元声明

private:
  friend class Human;
class Human{
public:

    //缺省构造/无参构造
    Human(int age = 0, const char* name="匿名"){
        //【int m_age;】,定义m_age,初值为随机数
        //【string m_name;】,定义m_name,利用m_name.string()
        cout << "Human类的缺省构造函数被调用" << endl;
        m_age = age;
        m_name = name;
    }
    //拷贝构造 带初始化表
	Human(const Human& that):m_age(that.m_age),m_name(that.m_name){
       //【int m_age;】,定义m_age,初值为随机数
       //【string m_name;】,定义m_name,利用m_name.string()
       cout << "Human类的拷贝构造函数被调用" << endl;
       m_age = that.m_age;
       m_name = that.m_name;
   }
   //拷贝赋值
   Human& operator=(const Human& that){
        // 编译器不会在自定义拷贝赋值函数中添加任何操作
        cout << "Human类的拷贝赋值函数被调用" << endl;
        this->m_age = that.m_age;
        this->m_name = that.m_name; 
        return *this;
    }
    Human(const Person& src)
    :m_age(src.p_age),m_name(src.p_name),m_score(src.p_score){
        cout << "Human类的类型转换构造函数被调用" << endl;
    }
private:
    int m_age;     // 基本类型的成员变量
    string m_name; // 类类型的成员变量
};

通过explicit关键字,可以强制这种通过类型转换构造函数实现的类型转换必须通过静态转换显式地进行

explicit Human(const Person& src)
:m_age(src.p_age),m_name(src.p_name),m_score(src.p_score){
    cout << "Human类的类型转换构造函数被调用" << endl;
}

2、析构函数

析构函数的函数名就是在类名前面加~
没有返回类型也没有参数,不能重载

在销毁对象之前一刻自动被调用,且仅被调用一次

  • 对象离开作用域
  • delete操作符

如果一个类没有定义析构函数,那么编译器会为其提供一个默认析构函数

功能

  • 对基本类型的成员变量,什么也不做
  • 对类类型的成员变量,调用相应类型的析构函数
  • 销毁 对象的各个成员变量

对象的销毁过程

自动执行的代码在自定义代码之后执行

  • 调用析构函数
    • 执行自己在析构函数中书写的代码
    • 利用成员变量调用相应的析构函数
    • 释放对象的各成员变量所占内存空间
  • 释放整个对象所占用的内存空间

使用说明

  • 通常情况下,若对象在其生命周期的最终时刻,并不持有任何动态分配的资源,可以不定义析构函数
  • 但若对象在其生命周期的最终时刻,持有动态资源则必须自己定义析构函数,释放对象所持有的动态资源
  • 析构函数的功能并不局限在释放资源上,它可以执行我们希望在对象被释放之前执行的任何操作

3、深拷贝

浅拷贝

无论是拷贝构造还是拷贝赋值,其默认实现对任何类型的指针成员都是简单地复制地址,而并不复制地址指向的数据,这种情况称之为浅拷贝。
浅拷贝的问题:
指向统一内存,free会多次,即delete多次同一内存地址

深拷贝

为了获得完整意义上的对象副本,必须自己定义拷贝构造和拷贝赋值,针对指针型成员变量深拷贝。

防止自赋值

相对于拷贝构造,拷贝赋值需要做更多的工作

  • 避免自赋值
  • 分配新资源
  • 拷贝新内容
  • 释放旧资源
  • 返回自引用

两个建议

  • 只有类中有指针型成员变量时才会涉及深浅拷贝的问题,因此应尽量避免使用指针型成员变量
  • 如果确实无法实现完整意义上的深拷贝拷贝构造和深拷贝拷贝赋值,可将它们私有化,禁止用户使用

类的静态成员

类的静态成员变量和静态成员函数,更象是普通的全局变量和全局函数,只是多了一层类作用域和访问控制限定符的约束,相当于具有成员访问属性的全局变量和全局函数

类的静态成员变量

静态成员变量 不属于对象 而属于类

  • 静态成员变量不包含在对象中,进程级生命期
  • 静态成员变量的定义和初始化,只能在类的外部而不能在构造函数中进行
  • 静态成员变量依然受类作用域和访问控制限定符的约束
  • 访问静态成员变量,既可以通过类也可以通过对象
  • 静态成员变量为该类的所有对象实例所共享

类的静态成员函数

静态成员函数 不属于对象 而属于类

  • 静态成员函数没有this指针,也没有常属性
  • 静态成员依然受类作用域和访问控制限定符的约束
  • 访问静态成员函数,既可以通过类也可以通过对象
  • 静态成员函数只能访问静态成员,而非静态成员函数既可以访问静态成员,也可以访问非静态成员

文章来源:https://blog.csdn.net/Edu_enth/article/details/134861128
本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。