c++中关于构造函数有参数的对象数组的初始化_C++中构造函数的手动和自动调用方式...

本文探讨了C++中构造函数的作用,特别是有参数的构造函数如何用于对象的初始化。通过代码示例,解释了对象定义与声明的区别,强调了构造函数在对象定义时的自动调用。此外,还介绍了如何手动调用构造函数,特别是在初始化对象数组时的场景。最后,通过一个数组类的实现,展示了面向对象编程如何增强原生数组的安全性和功能性。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

作者:子宇24 

链接:https://www.cnblogs.com/dishengAndziyu/p/10904899.html

1、对象的构造通过构造函数来完成,和类名相同且没有返回值,这个时候只有参   数一个特性,构造函数可以自定义参数,这个参数一般而言就是对类进行初始  化来使用的;带有参数的构造函数的意义在于可以使得每个对象有不同的初始   化状态(生活中每个事物必然包含自己的初始化状态,不如人的出生,面向对   象用来将生活中的事物映射的程序设计领域,所以现实世界的情况都必须可以  用面向对象的语言来描述,因此带有参数的构造函数就是非常必要的);

 2、带有参数的构造函数:

  • 构造函数可以根据需要定义参数;

  • 一个类中可以存在多个重载的构造函数;

  • 构造函数的重载遵循 C++ 重载的规则;

  • 代码示例:

class Test
{
public:
    Test(int v)
    {
        // use v to initialize member
    }
};

 3、对象定义和对象声明的区别:

  • 对象定义:申请对象的空间并调用构造函数;

    第一步,必须申请对象所占用的内存空间;

    第二步,调用构造函数;

  • 对象声明:告诉编译器存在这样一个对象;

    对象在哪里定义的不知道,链接的时候回去找;

    预处理,编译器对源代码进行检查并生成目标文件,链接器在各个目标文件中寻找目标文件存在的一些名字;

    对象声明时,没有对象定义时的两个步骤;

  • 代码示例:

Test t;  // 定义对象并调用构造函数;

Int main(){
    // 告诉编译器存在名为 t 的Test对象;
    extern Test t;

    return 0;
}
  • 对象的声明中可以在构造函数参数中给出默认值,对象的定义中不能够在构 造函数参数中给出默认值;

4、构造函数的自动调用(第一种初始化对象方式):

#include 

class Test
{
public:
    Test() 
    { 
        printf("Test()\n");
    }

    Test(int v) 
    { 
        printf("Test(int v), v = %d\n", v);
    }
};

int main(){
    Test t;      // 调用 Test()
    Test t1(1);  // 初始胡第一种方式的参数式自动调用,调用 Test(int v);这里也是定义对象,看上去非常像函数调用,但是这里是告诉编译器要调用带有参数的函数,由重载规则确定调用的是那个构造函数;
    Test t2 = 2; // 初始化第一种方式的赋值式自动调用,调用 Test(int v);C 语言中初始化的方法,定义一个变量后,立即指明一个值,通过赋值符号指明;这在面向对象中其实也是对象的定义,并且指明想用右值初始化左值;

    t = t2;  // 这是赋值操作,这里运行后不会调用构造函数,没有打印语句;初始化会调用构造函数,赋值则看后续课程;

    int i = 1;  // 用 1 对 i 进行初始化;
    i = 1;  // 用 1 对 i 进行赋值;赋值和初始化是不同的;在面向对象当中,不同在于初始化是要调用构造函数的;

    int i(100);  // 初始化的第二种写法,同 int i = 100;; 

    printf("i = %d\n", i);

    return 0;
}
  • 实验结果说明:

    初始化和赋值看上去相同之处在于当初始化用赋值符号表达的时候;

    不同之处在于初始化要调用构造函数,而赋值不会;

 5、构造函数的调用:

  • 一般情况下,构造函数在对象定义时被自动调用;

  • 一些特殊情况下,需要手工调用构造函数:

    如何创建对象数组;

 6、构造函数的手工调用(第二种初始化对象方式)编程实验:

#include 

class Test
{
private:
    int m_value;
public:
    Test() 
    { 
        printf("Test()\n");

        m_value = 0;
    }
    Test(int v) 
    { 
        printf("Test(int v), v = %d\n", v);

        m_value = v;
    }
    int getValue(){
        return m_value;
    }
};

int main(){
    Test ta[3];  // 按照 C 语言的方法定义 3 个 Test 对象的数组 ta;结果调用了 3 个 Test() 函数;

    for(int i=0; i<3; i++)  // 循环结果打印出 3 个 0,这不一定是我们想要的;编译器默认的调用了 Test();
    {
        printf("ta[%d].getValue() = %d\n", i , ta[i].getValue());
    }

    Test ta[3] = {Test(), Test(1), Test(2)};  // 手动调用构造函数;

    for(int i=0; i<3; i++)  // 循环结果为 0 1 2;分别调用了相应的构造函数;
    {
        printf("ta[%d].getValue() = %d\n", i , ta[i].getValue());
    }

    Test t = Test(100);  // 初始化第二种方式,手工调用构造函数;

    printf("t.getValue() = %d\n", t.getValue());

    return 0;
}

 7、小实例:

  • 需求:开发一个数组类解决原生数组的安全性问题:

    提供函数获取数组长度;

    C++ 要兼容 C 语言中的数组,但是 C 语言中的数组没有长度信息,用着用着就越界了;

    提供函数获取数组元素;

    提供函数设置数组元素;

 8、数组类的实现编程实验:

  • IntArray.h 文件:

#ifndef _INTARRAY_H_
#define _INTARRAY_H_

class IntArray
{
private:
    int m_length;
    int* m_pointer;
public:
    IntArray(int len);
    int length();
    bool get(int index, int& value);  // 用 bool 类型作为返回值是为了安全性,安全性的体现见数组类的实现;
    bool set(int index ,int value);
    void free();  // 用来释放 m_pointer 指向的堆空间
};

#endif
  • IntArray.cpp 文件:

#include "IntArray.h"

IntArray::IntArray(int len)  // 不加作用域分辨符时,是全局函数(此时仅名字前缀相同而已),所以要加作用域分辨符指明是数组类中的函数;
{
    m_pointer = new int[len];  // new int(len) 指的是设置初始值;

    for(int i=0; i    {
        m_pointer[i] = 0;
    }

    m_length = len;
}

int IntArray::length()
{
    return m_length;
}

bool IntArray::get(int index, int& value)
{
    bool ret = (0 <= index) && (index // 进行安全性检查,是安全性的体现;

    if( ret )
    {
        value = m_pointer[index];  // 通过引用返回一个值;
    }

    return ret;  // 越界则返回 false;
}

bool IntArray::set(int index, int value)
{
    bool ret = (0 <= index) && (index 
    if( ret )
    {
        m_pointer[index] = value;
    }

    return ret;
}

void IntArray::free()
{
    delete[]m_pointer;
}
  • IntArray 的使用:

#include 
#include "IntArray.h"

int main(){
    IntArray a(5);    

    for(int i=0; i    {
        a.set(i, i + 1);
    }

    for(int i=0; i    {
        int value = 0;

        if( a.get(i, value) )
        {
            printf("a[%d] = %d\n", i, value);
        }
    }

    a.free();

    return 0;
}
  • 这里展示了面向对象的强大,我们可以通过类来封装一些之前学习到的概念,并且可以将这些概念上的缺陷通过封装来弥补开来;

 9、小结:

  • 构造函数可以根据需要定义参数;

  • 构造函数之间可以存在重载关系;

  • 构造函数遵循 C++ 中重载函数的规则;

  • 对象定义时会触发构造函数的调用;

    构造函数调用方式分为自动调用和手工调用两种;

    自动调用的形式又分为参数式和赋值式;

    即初始化时,分为两种调用方式三种书写形式;

  • 在一些情况下可以手动调用构造函数;

此文为作者学习唐佐林老师的学习笔记,仅为交流共享之用。


●编号527,输入编号直达本文

●输入m获取文章目录

C语言与C++编程

b7376e0cb8c4cfb9a350cb16dd92fa10.png

分享C/C++技术文章

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值