利用父类的构造函数实现子类的构造函数

本文介绍了在C++中如何使用List类及其子类ArrayList和LinkedList的构造函数,特别是处理从父类继承的成员初始化问题,以及正确实现拷贝构造和析构函数以避免内存泄漏。
摘要由CSDN通过智能技术生成
1. 任务描述

使用List类的构造函数,实现其2个子类的构造函数。 List类已提供2个构造函数,其一是拷贝构造函数,另一个以1int作为参数,其作用是初始化size的值;同时int形参的默认值是0。 ArrayList类和LinkedList类均提供4个构造函数,请参考实训作业10实训作业11

2. 相关知识

考虑如下类:

class List{
protected:
    int size;
};
class ArrayList : public List{
public:
    ArrayList():size(0){}
};

你希望初始化一个空的ArrayList对象,因此size初始化为0。很遗憾,这是错误的,因为C++不允许这么做。因为构造函数初始化列表只能列出本类的成员,而size是从父类继承而来的,不是本类的成员。这个解释稍微有点拗口,但无论如何,C++不准这么做。 这样做就是合法的,因为sizeprotected

ArrayList::ArrayList(){size=0;}

同样很遗憾,这样做又不是初始化(请参考实训2)。而且,如果size是私有的,这样做也是行不通的。如何使用初始化列表初始化从父类继承而来的成员呢?答案是在初始化列表中调用父类的构造函数。当然这要求父类首先提供相应的构造函数。

class List{
protected:
    int size;
public:
    List(int s=0):size(s){}
};
class ArrayList : public List{
public:
    ArrayList():List(){}
               //在子类的初始化列表中调用父类的构造函数
};

以上就能成功的将ArrayList对象中的size初始化为0。这种情况下,即使sizeprivateArrayList类的构造函数仍然可以顺利执行。

3. 编程要求

本关一共有6个文件,List.h、ArrayList.h、LinkedList.h和main.cpp内容已写好,用户不允许改变。用户需要编写ArrayList.cpp和LinkedList.cpp中的内容,使得程序能够正确运行。 具体说来,需要提供头文件中指定的构造函数以及析构函数。

List.h内容如下:

#ifndef _LIST_H_
#define _LIST_H_
class List{
protected:
    int size;
public:
    //兼具默认构造函数和功能构造函数
    List(int s=0):size(s){}
    //拷贝构造函数
    List(const List&rhs):size(rhs.size){}
    
    //取函数,从此以后不再提供存函数
    int getSize()const{return size;}
};
#endif // _LIST_H_

ArrayList.h内容如下:

#ifndef _ARRAYLIST_H_
#define _ARRAYLIST_H_
#include "List.h"
class ArrayList : public List{
private:
    int *data;   //真正保存数据的地方
    int capacity;//容量
public:
    //默认构造函数,构造一个逻辑为空的顺序表
    ArrayList();
    //拷贝构造函数,构造一个逻辑上与参数内容相同的顺序表
    ArrayList(const ArrayList&rhs);
    //原生数组构造函数,构造一个内容与给定数组相同的顺序表
    ArrayList(int const a[],int n);
    //填充构造函数,构造一个内容为n个value的顺序表
    ArrayList(int n,int value);
    //析构函数,一定要自行实现,否则有内存泄漏
    ~ArrayList();
};
#endif // _ARRAYLIST_H_

LinkedList.h内容如下:

#ifndef _LINKEDLIST_H_
#define _LINKEDLIST_H_
#include "List.h"
class LinkedList : public List{
public:
    //这是单链表节点的结构体
    struct Node{
        int data;
        Node *next;
        Node(int a=0,Node *b=nullptr):data(a),next(b){}
    };
private:
    Node *head;//链表的头结点
public:
    //默认构造函数,构造一个逻辑为空的链表
    LinkedList();
    //拷贝构造函数,构造一个逻辑上与参数内容相同的链表
    LinkedList(const LinkedList&rhs);
    //原生数组构造函数,构造一个内容与给定数组相同的链表
    LinkedList(int const a[],int n);
    //填充构造函数,构造一个内容为n个value的链表
    LinkedList(int n,int value);
    //析构函数,一定要自行实现,否则有内存泄漏
    ~LinkedList();
};
#endif // _LINKEDLIST_H_

main.cpp内容如下:

#include <iostream>
#include "List.h"
#include "ArrayList.h"
#include "LinkedList.h"
using namespace std;
int const A[] = {100,200,300};
int main()
{
    List a;
    ArrayList b(A,3),c(4,9);
    ArrayList d(c);
    LinkedList e(A,3),f(4,9);
    LinkedList g(f);
    cout<<a.getSize()
        <<b.getSize()<<c.getSize()<<d.getSize()
        <<e.getSize()<<f.getSize()<<g.getSize()
        <<endl;
    return 0;
}

答案如下:

ArrayList.cpp内容如下:

#include "ArrayList.h"

// 默认构造函数,构造一个逻辑为空的顺序表
ArrayList::ArrayList() : capacity(0), data(nullptr) {}

// 拷贝构造函数,构造一个逻辑上与参数内容相同的顺序表
ArrayList::ArrayList(const ArrayList& rhs) : List(rhs), capacity(rhs.capacity) {
    data = new int[capacity];
    for (int i = 0; i < size; i++) {
        data[i] = rhs.data[i];
    }
}

// 原生数组构造函数,构造一个内容与给定数组相同的顺序表
ArrayList::ArrayList(int const a[], int n) : List(n), capacity(n) {
    data = new int[capacity];
    for (int i = 0; i < size; i++) {
        data[i] = a[i];
    }
}

// 填充构造函数,构造一个内容为n个value的顺序表
ArrayList::ArrayList(int n, int value) : List(n), capacity(n) {
    data = new int[capacity];
    for (int i = 0; i < size; i++) {
        data[i] = value;
    }
}

// 析构函数,一定要自行实现,否则有内存泄漏
ArrayList::~ArrayList() {
    delete[] data;
}

 LinkedList.cpp内容如下:

#include "LinkedList.h"

// 默认构造函数,构造一个逻辑为空的链表
LinkedList::LinkedList() : head(nullptr) {}

// 拷贝构造函数,构造一个逻辑上与参数内容相同的链表
LinkedList::LinkedList(const LinkedList& rhs) : List(rhs) {
    if (rhs.head == nullptr) {
        head = nullptr;
    } else {
        head = new Node(rhs.head->data);
        Node* curr = head;
        Node* rhsCurr = rhs.head->next;
        while (rhsCurr != nullptr) {
            curr->next = new Node(rhsCurr->data);
            curr = curr->next;
            rhsCurr = rhsCurr->next;
        }
    }
}

// 原生数组构造函数,构造一个内容与给定数组相同的链表
LinkedList::LinkedList(int const a[], int n) : List(n) {
    if (n == 0) {
        head = nullptr;
    } else {
        head = new Node(a[0]);
        Node* curr = head;
        for (int i = 1; i < n; i++) {
            curr->next = new Node(a[i]);
            curr = curr->next;
        }
    }
}

// 填充构造函数,构造一个内容为n个value的链表
LinkedList::LinkedList(int n, int value) : List(n) {
    if (n == 0) {
        head = nullptr;
    } else {
        head = new Node(value);
        Node* curr = head;
        for (int i = 1; i < n; i++) {
            curr->next = new Node(value);
            curr = curr->next;
        }
    }
}

// 析构函数,一定要自行实现,否则有内存泄漏
LinkedList::~LinkedList() {
    Node* curr = head;
    while (curr != nullptr) {
        Node* temp = curr;
        curr = curr->next;
        delete temp;
    }
}

  • 11
    点赞
  • 10
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值