размер ArrayList не известен, помогите - PullRequest
3 голосов
/ 23 июня 2011

У меня есть этот код

main.cpp

#include <iostream>
#include "functs.h"

using namespace std;

int main()
{
    ArrayList *al = new ArrayList;
    return 0;
}

functs.h

using namespace std;
#ifndef FUNCTS_H_INCLUDED
#define FUNCTS_H_INCLUDED

class ArrayList;
#endif // FUNCTS_H_INCLUDED

functs.cpp

#include <iostream>
#include "functs.h"

class ArrayList{
    public:
        void add(int num);
        void add(int num, int index);
        void remove(int index);
        void removeNum(int num);
        string toString();
        ArrayList(int init);
    private:
        void resize();
        int size, cap;
        int *myList[10];
};

void ArrayList::add(int num){
    if (size>=cap/2)
    {
        resize();
    }
    *myList[size] = num;
    size++;
}

void ArrayList::resize(){
    int temp[cap*2];
    int i;
    for (i = 0; i < size; i++)
    {
        temp[i] = *myList[i];
    }
    *myList = temp;
}

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

void ArrayList::add(int num, int index){
    int temp = *myList[index];
    int i;
    for (i = index; i < size; i++)
    {
        *myList[index] = num;
        num = temp;
        temp = *myList[i+1];
    }
    add(temp);
}

string ArrayList::toString(){
    string returnString = "{";
    int i;
    for (i = 0; i < size; i++)
        returnString.append(*myList[i] +",");
    returnString.replace(returnString.length()-1,1,"}");
    return returnString;
}

и я чрезвычайно новичок в C ++, но всякий раз, когда я пытаюсь скомпилировать код, он дает мне «размер ArrayList неизвестен». Пожалуйста, помогите мне разобраться в ошибке. = (

Ответы [ 4 ]

6 голосов
/ 23 июня 2011

Несмотря на проблемы проектирования / использования в вашем коде, наиболее очевидная проблема заключается в том, что вы хотите поместить определение класса в файл functs.h вместо файла functs.cpp:

functs.h:

// This is declaration is highly not recommended for use in header files.
// using namespace std;

#ifndef FUNCTS_H_INCLUDED
#define FUNCTS_H_INCLUDED

#include <string>

class ArrayList{
    public:
        void add(int num);
        void add(int num, int index);
        void remove(int index);
        void removeNum(int num);
        std::string toString();
        ArrayList(int init);
    private:
        void resize();
        int size, cap;
        int *myList[10];
};

#endif // FUNCTS_H_INCLUDED

functs.cpp:

#include "functs.h"

void ArrayList::add(int num){
    if (size>=cap/2)
    {
        resize();
    }
    *myList[size] = num;
    size++;
}

void ArrayList::resize(){
    int temp[cap*2];
    int i;
    for (i = 0; i < size; i++)
    {
        temp[i] = *myList[i];
    }
    *myList = temp;
}

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

void ArrayList::add(int num, int index){
    int temp = *myList[index];
    int i;
    for (i = index; i < size; i++)
    {
        *myList[index] = num;
        num = temp;
        temp = *myList[i+1];
    }
    add(temp);
}

std::string ArrayList::toString(){
    std::string returnString = "{";
    int i;
    for (i = 0; i < size; i++)
        returnString.append(*myList[i] +",");
    returnString.replace(returnString.length()-1,1,"}");
    return returnString;
}

templatetypedef указывает причину, по которой это необходимо.В основном, компилятор должен знать, сколько места нужно ArrayList, а class ArrayList; не предоставляет такой информации.


Не рекомендуется объявлять using namespace std; в заголовочном файле, потому чтотогда каждый, у кого есть файл functs.h (включая ваших клиентов!), также будет иметь using namespace std;, что увеличивает вероятность конфликтов имен.


Я настоятельно рекомендую вам подобрать aхорошая вводная книга по C ++ , если вы хотите изучать C ++ правильно.Вы демонстрируете в своем вопросе довольно большое непонимание того, как хорошо написан C ++.Это не значит, что вы некомпетентны как человек, но есть некоторые серьезные проблемы с кодом, который вы представляете.Просто перечислим несколько:

  • Стандартный C ++ уже предоставляет совершенно прекрасный класс массива под названием std::vector.Нет необходимости изобретать велосипед для того, что вы делаете.И даже если вам нужно заново изобрести колесо, глубокое понимание C ++ и большой опыт работы с C ++ являются необходимым условием для реализации контейнера массива, подходящего для производственного использования.
  • Открытый интерфейс вашего класса неполон.Клиенты не могут узнать, сколько элементов на самом деле находится в массиве.
  • int *myList[10]; объявляет массив fixed из 10 указателей на int.Это не подходит для класса массива.Особенно, если вы хотите, чтобы размер массива изменялся.
  • Недостаточно управления памятью, чтобы этот класс был полезен в любом смысле.Деструкторов нет, и, по-видимому, конструкторы не являются полными (и не совпадают), поэтому у вас нет реального логического места для размещения таких вещей, как new[] и delete[].
  • У вас есть ArrayList *al = new ArrayList;, ноу вас нигде нет соответствующего delete al;.Это утечка памяти.
  • Но последний момент - спорный вопрос, потому что вы должны использовать ArrayList a1; вместо ArrayList *al = new ArrayList;.Первый автоматически «удалит» себя в конце области (в данном случае, функции main()), в то время как последний требует оператора delete.C ++ не похож на Java, где автоматически собираются неиспользованные new 'ed объекты.

Я не могу комментировать правильность используемых вами алгоритмов, потому что (и я извиняюсь за этопотому что это будет звучать резко) то, что у вас есть, просто не сработает.Опять же, я рекомендую вам взять хорошую вводную книгу по С ++ , в которой будут рассмотрены такие вопросы.(Я должен подчеркнуть, что ни один из этих недостатков не является заявлением о вас как о личности. Я говорю конкретно о коде, который у вас есть в вашем вопросе.)

2 голосов
/ 23 июня 2011

Причина, по которой вы получаете эту ошибку, заключается в том, что в main.cpp компилятор не видел определения для класса ArrayList. Видно только объявление

class ArrayList;

При попытке создать ArrayList, написав

new ArrayList;

Компилятор не знает, сколько памяти необходимо для хранения ArrayList, потому что он не видел определения класса. Это отличается от других языков, таких как Java, где эта информация не обязательно должна быть доступна сразу.

Чтобы исправить это, обновите файл .h, переместив определение класса из файла .cpp. Таким образом, когда кто-то #include получает файл заголовка, он получает класс определение в дополнение к объявлению , которое позволит вам использовать new, объявить локальный переменные типа ArrayList и т. д.

Надеюсь, это поможет!

0 голосов
/ 23 июня 2011

То, как вы объявили myList, имеет фиксированный размер;*myList = temp; делает не то, что вам нужно.

Объявите myList просто как int * myList;

В конструкторе используйте myList = new int[10];

Везде, где есть*myList[...] измените его на myList[...]

При изменении размера int temp[cap*2] должно быть int *temp = new int[cap * 2], а *myList = temp должно быть myList = temp

У вас останется памятьутечка, но это должно начать вас.

0 голосов
/ 23 июня 2011

Это много

class ArrayList{
    public:
        void add(int num);
        void add(int num, int index);
        void remove(int index);
        void removeNum(int num);
        string toString();
        ArrayList(int init);
    private:
        void resize();
        int size, cap;
        int *myList[10];
};

Должно быть в файле .h.

Почему?Потому что объявление класса (когда вы пишете class ArrayList;) достаточно только тогда, когда размер класса не нужен (более конкретные случаи перечислены в стандарте C ++).Определение класса должно появляться в той же единице перевода, в которой класс используется таким образом, каким он должен быть завершен.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...