Reputation: 1886
I am currently working on template classes (and I am quite lost). I want to build a template class that can stores objects.
Here is my .h file :
#ifndef STORAGE_H_
#define STORAGE_H_
#include <iostream>
using namespace std;
template<class T,int maxsize>
class Storage
{
public:
Storage();
int getSize();
T get(int index);
bool add(T element);
private:
T array[maxsize];
int length;
};
template<class T,int maxsize>
Storage<T,maxsize>::Storage()
: length(0),// Liste d'initialisation des données membres
{}
template<class T,int maxsize>
int Storage<T,maxsize>::getSize()
{
return length;
}
template<class T,int maxsize>
T Storage<T,maxsize>::get(int index)
{
return array[index];
}
template<class T,int maxsize>
bool Storage<T,maxsize>::add(T element)
{
if (length>=maxsize) return false;
array[length++]=element;
return true;
}
#endif /* STORAGE_H_ */
It works fine when i'm dealing with int for instance. But when it comes to others objects I previously made it fails. In my main .cpp file :
Storage<Pokemon,4> pokemonArray;
Which sends me the following error :
no matching function for call to 'Pokemon::Pokemon()'
Pokemon being a class I have. To me this line means that it can't find the constructor Pokemon().
How can I make it work ?
Thank you guys !
Upvotes: 1
Views: 1135
Reputation: 45704
You error is simple:
You are using initialized storage.
Use uninitialized storage to store those members, like with an anonymous union.
As you have taken over lifetime-management of the contained T
elements, you need to write your own copy-ctor, move-ctor, copy-assignment, move-ctor and destructor.
An alternative is re-using a standard-container already doing that for you with dynamic storage, but it looks like you wanted to build your own and avoid the heap.
Or, you know, make sure your types are default-constructible by giving them a default-ctor.
Upvotes: 1
Reputation: 37914
The following code will work, assuming that Pokemon has a default constructor:
#include <iostream>
using namespace std;
template<class T,int maxsize>
class Storage
{
public:
Storage();
int getSize();
T get(int index);
bool add(T element);
private:
T array[maxsize];
int length;
};
template<class T,int maxsize>
Storage<T,maxsize>::Storage()
: length(0)
{}
template<class T,int maxsize>
int Storage<T,maxsize>::getSize()
{
return length;
}
template<class T,int maxsize>
T Storage<T,maxsize>::get(int index)
{
return array[index];
}
template<class T,int maxsize>
bool Storage<T,maxsize>::add(T element)
{
if (length>=maxsize) return false;
array[length++]=element;
return true;
}
class Pokemon{
public: Pokemon(){};
};
int main(){
Storage<Pokemon,4> pokemonArray;
}
Note that if no constructor was given, the compiler would generate one automatically and the code would still compile.
class Pokemon{
//no constructors is still ok
};
The default constructor is called implicitly by the Array inside your Storage class. You most likely have a non-trivial constructor in your Pokemon class which is causing the problem. Perhaps something like this:
class Pokemon{
public:
Pokemon(std::string name){
//....
}
//...
};
When you provide a non-trivial constructor, the compiler will not add one implicitly, and thus, you either need to change your Storage class, or give the Pokemon class a default constructor along side your current constructor(s):
class Pokemon{
public:
Pokemon(){}; //<-- needed
Pokemon(std::string name){ ... }; //<-- optional
};
Upvotes: 2
Reputation: 43662
Since your Storage
templated class has an array of fixed size T
(i.e. Pokemon
objects):
template<class T, int maxsize>
class Storage
{
public:
Storage();
int getSize();
T get(int index);
bool add(T element);
private:
T array[maxsize]; // Array
int length;
};
when you try to instantiate an object of that class you should make sure that the Pokemon
class has a visible default constructor to initialize that array of objects. The following won't work for instance:
class Pokemon {
public:
Pokemon() = delete;
};
int main(void)
{
Storage<Pokemon, 4> pokemonArray;
return 0;
}
Solution: make sure the class has a default constructor or change your design (what about a std::vector
of smart pointers for the internal storage?)
Upvotes: 1