开发者

Why can't I make objects in C++ have data-members that are other objects?

I was bored one day, so I made this library:

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;
};

and then I tested it, and it worked. So now I am trying to create an experiment whose source code is this:

#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;
}

and it is returning the error:

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>&)

I have made a whole lot of tests, and no matter what I do, I can't seem to initialize an object that is the data-member of another object. I just don't understand why.


You declare a constructor that takes parameters for 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;
};

And then try to allocate HASH<string, int> in OBJECT::OBJECT:

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

You just need to pass name and number to HASH<string, int>'s constructor:

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


brain.cpp: In constructor ‘OBJECT::OBJECT(std::string, int)’: brain.cpp:10: error: no matching function for call to ‘HASH, std::allocator >, int>::HASH()’

It's right. You haven't defined a default constructor for your HASH class.


There is no default constructor:

int_properties=new HASH <string, int>; // No constructor that takes zero arguments to HASH


There is no default constructor for your HASH class. Your constructor of OBJECT should be

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


In C++ objects can certainly be data members of other objects. Otherwise you would only have classes composed of primitive types, and that would be of little use.

The problem here is that your class HASH does not have a default constructor.

If you do not specify a constructor at all, then the compiler will create a deafault constructor for you. But as soon as you define a non-default constructor, the compiler will no longer supply a default one.

So either you have to pass an element and a key to the HASH object that you are creating, or you have to give class HASH a default constructor, that would presumably create an empty hash table.


int_properties = new HASH <string, int>;

This line attempts to call the default constructor of class HASH<string, int>. That is, it tries to call a constructor with zero objects. But there is no such constructor. The constructor you defined is HASH<string, int>::HASH(string element, int key), which requires two arguments.

Template parameters appear in <>. Function parameters appear in (). Don't confuse the two.

You can fix this either by using the constructor you defined by adding some function arguments:

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

or by modifying or overloading your constructor so that it can take zero arguments and be a default constructor.

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

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


HASH is a template class and you cannot instantiate it directly.

0

上一篇:

下一篇:

精彩评论

暂无评论...
验证码 换一张
取 消

最新问答

问答排行榜