C++ 动态对象数组的知识总结

默认构造函数

    首先,我们来看一下是什么是默认构造函数,如下面一段代码:

#include<iostream>
#include<math.h>
using namespace std;
class Point
{
    double x, y;
public:
    void print();
    Point(double a=0,double b=1){x=a;y=b;}  //默认构造函数
    Point(double a){x=1;y=1;} //构造函数
    Point(){} //默认构造函数

};
void Point::print()
{
    cout << x << " " << y << endl;
}

    所以,可以知道默认构造函数总得来说是可以在对象生成的时候,不需要传入参数,对应情况就是:

Point point;   
Point *point=new Point;

    非默认构造函数就是必须要传参。关于默认构造函数有以下知识点:

  • 程序没有定义任何构造函数,则有默认的构造函数Point(){},里面的成员的值没有初始化
  • 定义默认构造函数有两种方式,如上述代码展示的,一是定义一个无参的构造函数,二是定义所有参数都有默认值的构造函数
  • 注意:一个类只能有一个默认构造函数!也就是说上述两种方式不能同时出现,一般选择 Point(); 这种形式的默认构造函数

带默认构造函数的动态数组

    我们来看一下如果一个类带默认构造函数,如下代码是生成静态和动态数组的:

#include<iostream>
#include<math.h>
using namespace std;
class Point
{
    double x, y;
public:
    void print();

};
void Point::print()
{
    cout << x << " " << y << endl;
}
int main() {
    //静态对象数组
    Point pp[5];      
    for (int i = 0; i<5; i++)
        pp[i].print();
    //动态对象数组
    Point *p = new Point[5]; //这里面5也可以是变量
    for (int i = 0; i<5; i++)
            p[i].print();
    //别忘记delete相应的空间
}

    可以看出来,如果一个类带默认构造函数的话,那么生成的时候就不需要传入参数了,方便了不少。

没有默认构造函数的动态数组

    如果一个类没有默认构造函数呢,这种情况就需要传入参数了,如下代码:

#include<iostream>
#include<math.h>
using namespace std;
class Point
{
    double x, y;
public:
    Point(double a, double b);
    void print();
};
Point::Point(double a, double b)
{
    x = a;
    y = b;
}
void Point::print()
{
    cout << x << " " << y << endl;
}
int main()
{
    Point *p[5];//静态指针数组
    for (int i = 0; i < 5; i++) {
        p[i] = new Point(i, i);    //其中你可以用自己的方式来初始化对象,例如从键盘接收值等
    }
    for (int i = 0; i < 5; i++) {
        p[i]->print();
    }
    Point **pp = new Point *[5];  //动态指针数组,5也可以是变量
    for (int i = 0; i < 5; i++) {
        pp[i] = new Point(i, i);
    }
    for (int i = 0; i < 5; i++) {
        pp[i]->print();
    }
    //别忘了delete相应的空间
    return 0;
}

    静态指针数组是定义了一些的Point指针,通过new的方式来使每个指针指向对象。动态指针数组是分配固定大小的连续空间,里面的每个元素类型是Point *,然后把这连续空间的首地址给pp,pp是指向Point *类型的指针。

注意是 new Point *[5]而不是 new (Point *)[5],后者编译器会报错

new多维数组

int *p=new int[2];
int *p=new int[2][3];  //错误
int (*p)[3]=new int[2][3];  //正确
int (*p)[4][5]=new int[2][4][5]; //正确

    为啥第二行就错误呢?其实我们可以这样理解:

  • int (*p)[3]其中p是指针,这是毋庸置疑的,那这个指针指向什么类的数据呢?我们改一下写法,编程int[3] (*p),是不是就很简洁明了呢?p指向的类型是int[3]。
  • new int[2][3]返回的2个int[3]类型的数组的首地址,赋值给p。
  • 同理,第四行p指向的类型是int[4][5],new int[3][4][5]返回的是3个int[4][5]类型的数组的首地址,赋值给p。
  • 针对第一行的情况,如果p的一开始地址为1000,假设int占用4个字节,那么执行p++以后,p的地址为1000+4,第三行的情况,如果p的一开始地址为1000,进行p++以后,p的请值为1000+4*3,以此类推,第四行p++以后p的值为1000+4*4*5。
  • 45
    点赞
  • 224
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 9
    评论
运行界面: Computer 1: Model: Lenovo Price: 5000 Manufacturer: China Computer 2: Model: HP Price: 6000 Manufacturer: USA Computer 3: Model: Dell Price: 7000 Manufacturer: USA Copied Computer: Model: HP Price: 6000 Manufacturer: USA Destructor is called for Dell Destructor is called for HP Destructor is called for HP Destructor is called for Lenovo 代码如下: #include <iostream> #include <cstring> using namespace std; class Computer { private: char model[20]; int price; char manufacturer[20]; public: Computer() { strcpy(model, "Unknown"); price = 0; strcpy(manufacturer, "Unknown"); } Computer(char m[], int p, char manu[]) { strcpy(model, m); price = p; strcpy(manufacturer, manu); } Computer(const Computer& c) { strcpy(model, c.model); price = c.price; strcpy(manufacturer, c.manufacturer); cout << "Copy constructor is called for " << model << endl; } ~Computer() { cout << "Destructor is called for " << model << endl; } void setData(char m[], int p, char manu[]) { strcpy(model, m); price = p; strcpy(manufacturer, manu); } void displayData() { cout << "Model: " << model << endl; cout << "Price: " << price << endl; cout << "Manufacturer: " << manufacturer << endl; } }; int main() { Computer computers[3]; computers[0].setData("Lenovo", 5000, "China"); computers[1].setData("HP", 6000, "USA"); computers[2].setData("Dell", 7000, "USA"); Computer copied(computers[1]); cout << "Computer 1:" << endl; computers[0].displayData(); cout << "Computer 2:" << endl; computers[1].displayData(); cout << "Computer 3:" << endl; computers[2].displayData(); cout << "Copied Computer:" << endl; copied.displayData(); return 0; } 分析和总结: 本题主要考察了面向对象编程的基本知识,如类的定义、构造函数、析构函数、数据封装等。在解决问题过程中,需要注意以下几点: 1. 在构造函数中,可以使用重载或默认值的方式来定义函数,以满足不同的创建需求。 2. 复制构造函数是一种特殊的构造函数,用于从一个已有的对象中创建一个新的对象。在复制构造函数中,需要完成数据的复制,并且可以使用cout语句来验证函数是否被调用。 3. 析构函数是一个与构造函数相对应的函数,用于释放对象占用的内存空间。在析构函数中,可以使用cout语句来验证函数是否被调用。 4. 在类的成员函数中,可以使用数据封装的方式来隐藏数据的具体实现,从而保证数据的安全性。 5. 在主函数中,需要使用对象数组的方式来创建多个对象,并且可以使用复制构造函数来创建一个新的对象。在测试过程中,需要使用displayData函数来输出对象的数据成员值。 总之,本题旨在让考生掌握基本的面向对象编程知识,包括类的定义、构造函数、析构函数、数据封装等。在日常编程中,这些知识都是非常基础且重要的,可以帮助我们更好地组织程序结构,提高代码的可读性和可维护性。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 9
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

CuteXiaoKe

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值