Почему я не могу заставить объекты в C ++ иметь члены-данные, которые являются другими объектами? - PullRequest
0 голосов
/ 03 декабря 2010

Мне было скучно однажды, поэтому я сделал эту библиотеку:

template <class X, class Y> class HASH
{
public:
HASH(X element, Y key)
{
    elements=new X[0];
    keys=new Y[0];
    keys[0]=key;
    elements[0]=element;
    num_elements=0;
};
~HASH ()
{
    delete[] elements;
    delete[] keys;
};
void Add(X element, Y key)
{
    for (int x=0; x<=num_elements; x++)
    {
        if (keys[x]==key)
        {
            throw(key);
        }
    }
    //make copy variables
    X *copy_elements=new X[num_elements];
    Y *copy_keys=new Y[num_elements];
    //copy all the elements
    for (int x=0; x<=num_elements; x++)
    {
        copy_elements[x]=elements[x];
        copy_keys[x]=keys[x];
    }
    //delete the originals
    delete[] elements;
    delete[] keys;
    //resize the originals
    elements=new X[num_elements+1];
    keys=new Y[num_elements+1];
    //copy everything back to the originals
    for (int x=0; x<=num_elements; x++)
    {
        elements[x]=copy_elements[x];
        keys[x]=copy_keys[x];
    }
    //delete the copies
    delete[] copy_keys;
    delete[] copy_elements;
    //increment num_elements
    num_elements++;
    //add the new elements
    elements[num_elements]=element;
    keys[num_elements]=key;
};
X operator [] (Y key)
{
    int num=0;
    for (int x=0; x<=num_elements; x++)
    {
        if (keys[x]==key)
        {
            num=x;
            break;
        }
    }
    return elements[num];
};
Y KeyNum(int x)
{
    return keys[x];
};
int NumElements()
{
    return num_elements;
};
private:
int num_elements;
X *elements;
Y *keys;
};

и затем я проверил это, и это работало. Поэтому сейчас я пытаюсь создать эксперимент с исходным кодом:

#include <hash.cpp>
#include <iostream>
using namespace std;

class OBJECT 
{
    public:
        OBJECT(string name, int number)
        {
            int_properties=new HASH <string, int>;
        };
        ~OBJECT()
        {
            delete int_properties;
        };
        HASH <string, int> *int_properties;
};

int main()
{
    OBJECT a("name", 5);
    return 0;
}

и возвращается ошибка:

brain.cpp: In constructor ‘OBJECT::OBJECT(std::string, int)’:
brain.cpp:10: error: no matching function for call to ‘HASH<std::basic_string<char, std::char_traits<char>, std::allocator<char> >, int>::HASH()’
/usr/include/hash.cpp:4: note: candidates are: HASH<X, Y>::HASH(X, Y) [with X = std::basic_string<char, std::char_traits<char>, std::allocator<char> >, Y = int]
/usr/include/hash.cpp:2: note:                 HASH<std::basic_string<char, std::char_traits<char>, std::allocator<char> >, int>::HASH(const HASH<std::basic_string<char, std::char_traits<char>, std::allocator<char> >, int>&)

Я провел множество тестов, и независимо от того, что я делаю, я не могу инициализировать объект, являющийся членом данных другого объекта. Я просто не понимаю, почему.

Ответы [ 7 ]

2 голосов
/ 03 декабря 2010

Вы объявляете конструктор, который принимает параметры для HASH<X, Y>:

HASH(X element, Y key)
{
    elements=new X[0];
    keys=new Y[0];
    keys[0]=key;
    elements[0]=element;
    num_elements=0;
};

А затем попробуйте выделить HASH<string, int> в OBJECT::OBJECT:

OBJECT(string name, int number)  
{  
    int_properties=new HASH <string, int>;  
};  

Вам просто нужно передать name и number конструктору HASH<string, int>:

    int_properties=new HASH <string, int>(name, number);
1 голос
/ 03 декабря 2010
int_properties = new HASH <string, int>;

Эта строка пытается вызвать конструктор по умолчанию class HASH<string, int>. То есть он пытается вызвать конструктор с нулевыми объектами. Но такого конструктора не существует. Определенный вами конструктор - HASH<string, int>::HASH(string element, int key), для которого требуется два аргумента.

Параметры шаблона отображаются в <>. Параметры функции отображаются в (). Не путайте их.

Это можно исправить с помощью определенного вами конструктора, добавив несколько аргументов функции:

int_properties = new HASH<string, int> (name, number);

или путем изменения или перегрузки вашего конструктора, чтобы он мог принимать нулевые аргументы и являлся конструктором по умолчанию.

template <class X, class Y> class HASH {
public:
  HASH();
  //...
};

template <class X, class Y> HASH<X,Y>::HASH() { /*...*/ }
1 голос
/ 03 декабря 2010

Для вашего класса HASH нет конструктора по умолчанию.Ваш конструктор OBJECT должен быть

OBJECT(string name, int number)
{
   int_properties=new HASH <string, int>(name, number);
};
1 голос
/ 03 декабря 2010

Нет конструктора по умолчанию:

int_properties=new HASH <string, int>; // No constructor that takes zero arguments to HASH
1 голос
/ 03 декабря 2010

В C ++ объекты, безусловно, могут быть членами данных других объектов. В противном случае у вас будут только классы, составленные из примитивных типов, и это будет бесполезно.

Проблема в том, что ваш class HASH не имеет конструктора по умолчанию.

Если вы вообще не указываете конструктор, то компилятор создаст для вас конструктор по умолчанию. Но как только вы определили конструктор не по умолчанию, компилятор больше не будет предоставлять конструктор по умолчанию.

Так что либо вы должны передать элемент и ключ создаваемому объекту HASH, либо вы должны предоставить class HASH конструктор по умолчанию, который предположительно создаст пустую хеш-таблицу.

1 голос
/ 03 декабря 2010
brain.cpp: In constructor ‘OBJECT::OBJECT(std::string, int)’: brain.cpp:10: error: no matching function for call to ‘HASH, std::allocator >, int>::HASH()’

Это правильно.Вы не определили конструктор по умолчанию для вашего класса HASH.

0 голосов
/ 03 декабря 2010

HASH является классом шаблона, и вы не можете создать его экземпляр напрямую.

...