c ++构造函数的详细说明

电脑杂谈  发布时间:2020-07-29 12:02:07  来源:网络整理

学术期刊a类b类c类_c++类构造函数_c++ 函数指针 指针函数

各种C ++教科书中都介绍了c ++构造函数的知识,但是初学者经常很少注意观察和总结各种构造函数的特性和用法c++类构造函数,因此我根据自己的C ++编程经验对其进行了总结. 让我们看一下C ++中各种构造函数的特性,并附上示例,希望对初学者有所帮助.

1. 构造函数做什么?

class Counter
{
public:
    // 类Counter的构造函数
    // 特点:以类名作为函数名,无返回类型
    Counter()
    {
        m_value = 0;
    }
         
private:     
    // 数据成员
  int m_value;
}

c++类构造函数_c++ 函数指针 指针函数_学术期刊a类b类c类

创建此类对象时,编译器系统对象会分配内存空间并自动调用构造函数->构造函数完成成员的初始化

例如: 计数器c1;

编译系统为对象c1的每个数据成员(m_value)分配内存空间,并调用构造函数Counter()自动初始化对象c1的m_value并将其设置为0

c++类构造函数_c++ 函数指针 指针函数_学术期刊a类b类c类

因此: 构造函数的作用: 初始化对象的数据成员.

2. 构造函数的类型

class Complex 
{         
private :
    double m_real;
    double m_imag;
public:
    // 无参数构造函数
    // 如果创建一个类你没有写任何构造函数,则系统会自动生成默认的无参构造函数,函数为空,什么都不做
    // 只要你写了一个下面的某一种构造函数,系统就不会再自动生成这样一个默认的构造函数,如果希望有一个这样的无参构造函数,则需要自己显示地写出来
    Complex(void)
    {
         m_real = 0.0;
         m_imag = 0.0;
    } 
        
    // 一般构造函数(也称重载构造函数)
    // 一般构造函数可以有各种参数形式,一个类可以有多个一般构造函数,前提是参数的个数或者类型不同(基于c++的重载函数原理)
    // 例如:你还可以写一个 Complex( int num)的构造函数出来
    // 创建对象时根据传入的参数不同调用不同的构造函数
    Complex(double real, double imag)
    {
         m_real = real;
         m_imag = imag;         
     }
    
    // 复制构造函数(也称为拷贝构造函数)
    // 复制构造函数参数为类对象本身的引用,用于根据一个已存在的对象复制出一个新的该类的对象,一般在函数中会将已存在对象的数据成员的值复制一份到新创建的对象中
    // 若没有显示的写复制构造函数,则系统会默认创建一个复制构造函数,但当类中有指针成员时,由系统默认创建该复制构造函数会存在风险,具体原因请查询有关 “浅拷贝” 、“深拷贝”的文章论述
    Complex(const Complex & c)
    {
        // 将对象c中的数据成员值复制过来
        m_real = c.m_real;
        m_img  = c.m_img;
    }            
    // 类型转换构造函数,根据一个指定的类型的对象创建一个本类的对象
    // 例如:下面将根据一个double类型的对象创建了一个Complex对象
    Complex::Complex(double r)
    {
        m_real = r;
        m_imag = 0.0;
    }
    // 等号运算符重载
    // 注意,这个类似复制构造函数,将=右边的本类对象的值复制给等号左边的对象,它不属于构造函数,等号左右两边的对象必须已经被创建
    // 若没有显示的写=运算符重载,则系统也会创建一个默认的=运算符重载,只做一些基本的拷贝工作
    Complex &operator=(const Complex &rhs)
    {
        // 首先检测等号右边的是否就是左边的对象本,若是本对象本身,则直接返回
        if ( this == &rhs ) 
        {
            return *this;
        }
            
        // 复制等号右边的成员到左边的对象中
        this->m_real = rhs.m_real;
        this->m_imag = rhs.m_imag;
            
        // 把等号左边的对象再次传出
        // 目的是为了支持连等 eg:    a=b=c 系统首先运行 b=c
        // 然后运行 a= ( b=c的返回值,这里应该是复制c值后的b对象)    
        return *this;
    }
};

c++类构造函数_c++ 函数指针 指针函数_学术期刊a类b类c类

以下使用上面定义的类对象说明每个构造函数的用法:

void main()
{
    // 调用了无参构造函数,数据成员初值被赋为0.0
    Complex c1,c2;
    // 调用一般构造函数,数据成员初值被赋为指定值
    Complex c3(1.0,2.5);
    // 也可以使用下面的形式
    Complex c3 = Complex(1.0,2.5);
        
    // 把c3的数据成员的值赋值给c1
    // 由于c1已经事先被创建,故此处不会调用任何构造函数
    // 只会调用 = 号运算符重载函数
    c1 = c3;
        
    // 调用类型转换构造函数
    // 系统首先调用类型转换构造函数,将5.2创建为一个本类的临时对象,然后调用等号运算符重载,将该临时对象赋值给c1
    c2 = 5.2;
      
    // 调用拷贝构造函数( 有下面两种调用方式) 
    Complex c5(c2);
    Complex  = c2;  // 注意和 = 运算符重载区分,这里等号左边的对象不是事先已经创建,故需要调用拷贝构造函数,参数为c2       
        
}

3. 思考与测验

c++ 函数指针 指针函数_c++类构造函数_学术期刊a类b类c类

(1)为什么要在函数中直接访问对象c的私有成员?

Complex(const Complex & c)
{
    // 将对象c中的数据成员值复制过来
    m_real = c.m_real;
    m_img = c.m_img;
}

(2)挑战问题,了解报价和按价值传递之间的区别

Complex test1(const Complex& c)
{
    return c;
}
  
Complex test2(const Complex c)
{
    return c;
}
   
Complex test3()
{
    static Complex c(1.0,5.0);
    return c;
}
  
Complex& test4()
{
    static Complex c(1.0,5.0);
    return c;
}
  
void main()
{
    Complex a,b;
   
    // 下面函数执行过程中各会调用几次构造函数,调用的是什么构造函数?
    
    test1(a);
    test2(a);
     
    b = test3();
    b = test4();
     
    test2(1.2);
    
    // 下面这条语句会出错吗?
    test1(1.2);     
    
    //test1( Complex(1.2 )) 呢?
}

4. 浅拷贝和深拷贝

如上所述,如果没有自定义副本构造函数,则系统将创建一个默认副本构造函数c++类构造函数,但系统创建的默认副本构造函数将仅执行“浅表副本”,即“要复制的对象逐一分配给新创建的对象. 如果类的数据成员中有一个指针成员,则新对象的指针所指向的地址将与复制对象的指针所指向的地址相同. 删除指针时,将导致两次重复删除错误. 这是一个示例:


本文来自电脑杂谈,转载请注明本文网址:
https://www.pc-fly.com/a/jisuanjixue/article-288940-1.html

    相关阅读
      发表评论  请自觉遵守互联网相关的政策法规,严禁发布、暴力、反动的言论

      • 陈旺
        陈旺

        参战舰船也超过北洋海军的数量

      • 陈俊东
        陈俊东

        是否落后你也并不清楚

      • 李恒科
        李恒科

        非主流哥哥

      热点图片
      拼命载入中...