How to create an object with class template?

3

I have this code:

Main.cpp

Warehouse<Base<int>> arm(1, 1, 1, 1);
arm.createSubBase(1,1,1);

Warehouse.h

private:
 vector<Base<T>*> whouse;
public :
 void createSubBase(int, int, int);

template <class T> 
void Warehouse<T>::createSubBase(int,int,int) {
  Base<T>* dN = new SubBase<T>(int,int,int,int); ***<-ERROR MESSAGE:" in file included from"***
     whouse.push_back(dN);
}

Base.h

template <class T>
class Base {
private:
 int I,a,b,c;
public :
  Base(int,int,int,int);
}

template <class T>
Base<T>::Base(int i, int a, int b, int c) {
    this -> I = i;
    this -> a= a;
    this -> b= b;
    this -> c = c;
}

SubBase.h

template <class T>
class SubBase: public Base<T> {
public:
  SubBase(int, int, int,int);
}
template <class T>
SubBase<T>::SubBase(int, int, int , int) : Depositos<T>(int,int,int,int) {...}

Does anyone know why you're giving me that error message? It gives me this message and gives me error in the vector include.

I do not understand why I can not create this object:

Base < T > * b = new subbase < T > ( int , int , int );
    
asked by anonymous 25.10.2014 / 16:48

1 answer

4

There's so much wrong with your code that it's hard to know where to start.

First of all, you did not put the original code, nor the original error message. When you edited the code to put it here, it probably inserted a lot of other errors. Hence I do not know if the errors I see are the originals or those inserted in the edition. For example, most likely you renamed your class Depositos to Base while posting, but forgot to update the SubBase constructor, but you can not be sure where Depositos came from without seeing the original code. / p>

That said, your use of templates does not make sense, since at any time you use or instantiate variables of type T. Did you happen to want to declare your class Base as being the following?

template <class T>
class Base {
private:
 T I,a,b,c;
public :
  Base(T, T, T, T);
};
So it makes more sense to use a template, but I would need to change more things to work ... anyway, I picked up the pieces of code you posted, put it together into a single file, and I was modifying it until I compiled it. It looks like this:

#include <vector>

using namespace std;

template <class T>
class Base {
private:
 int I,a,b,c;
public :
  Base(int,int,int,int);
};

template <class T>
Base<T>::Base(int i, int a, int b, int c) {
    this -> I = i;
    this -> a= a;
    this -> b= b;
    this -> c = c;
}

template <class T>
class SubBase: public Base<T> {
public:
  SubBase(int, int, int,int);
};

template <class T>
SubBase<T>::SubBase(int i, int a, int b, int c):
    Base<T>(i,a,b,c)
{
}

template <class T>
class Warehouse {
private:
 vector<Base<T>*> whouse;
public :
 void createSubBase(int, int, int);
};

template <class T> 
void Warehouse<T>::createSubBase(int A, int B, int C) {
  Base<T>* dN = new SubBase<T>(A, B, C, 42);
  whouse.push_back(dN);
}

int main()
{
  Warehouse<Base<int>> arm;
  arm.createSubBase(1,1,1);
}

The first problem I noticed was that you forgot the semicolon ; in the final class declaration. The specific function you pointed out as being wrong was like this:

template <class T>
void Warehouse<T>::createSubBase(int,int,int) {
   Base<T>* dN = new SubBase<T>(int,int,int,int);
   whouse.push_back(dN);
}

And in my version it looks like this:

template <class T> 
void Warehouse<T>::createSubBase(int A, int B, int C) {
  Base<T>* dN = new SubBase<T>(A, B, C, 42);
  whouse.push_back(dN);
}

Basically, you were calling the constructor that gets 4 int s, but it was not passing any value on them. In my version, I pass the same parameters that the createSubBase function receives, plus 42 as the last parameter.

You did the same thing here:

SubBase<T>::SubBase(int, int, int , int) : Depositos<T>(int,int,int,int) {...}

that is, instead of passing the due parameters, you wrote int instead of each of them (not counting that you wrote Depositos instead of Base ). My equivalent looks like this:

SubBase<T>::SubBase(int i, int a, int b, int c): Base<T>(i,a,b,c) {}

That is, the function does nothing, but compiles (your had ellipsis in place of the content, this certainly does not compile, but it's certainly an issue of yours before posting).

Finally, you marked the question with the tag "C ++ 11" and, in fact, used a C ++ 11 functionality, that is, a feature that was only included in the C ++ version published in 2011, which is:

Warehouse<Base<int>> arm;

In the previous version of C ++, this code is invalid, and should have a space between the two signs of > :

Warehouse<Base<int> > arm;

I kept this particularity in my version of the code, so to compile I had to use the following command (using the compiler Clang ):

$ clang ++ -std = c ++ 11 -the warehouse.cpp warehouse

or, in the GNU compiler:

$ g ++ -std = c ++ 11 -the warehouse.cpp warehouse

This command -std=c++11 is only necessary because you do not give space between the two > at the end of instantiation of the template.

Well, this was all just the compilation errors, because your code still has conceptual errors, bad practices and at least 2 bugs.

As I said, you do not use the template value at all. And that's precisely why the code compiles. The Warehouse instantiated in the following line:

'Warehouse<Base<int>> arm;'

will have its type T = Base<int> , so the vector internal to it will be of type:

vector<Base<Base<int>>*> whouse; // Simplesmente substitui T pelo tipo Base<int>

You probably wanted to:

vector<Base<int>*> whouse;

and therefore should have instantiated as:

Warehouse<int> arm;

But like I said, the way it's compiled, because in the end, inside Base , type T is not used at all.

One bug is that you call new and allocate memory, but it does not call delete anywhere. You should implement the destructor of your class, and call delete for all elements of your whouse vector, failing to do so causes a problem called memory leak.

The bad practice is that you have nothing to gain (except for the memory leak bug) when managing pointers explicitly with new and delete . In your case, I find it much better to use a smart pointer, which automatically manages memory for you, such as std::shared_ptr or std::unique_ptr (both available only in C ++ 11).

The other bug is that your Base destructor should be virtual, otherwise the object is not properly destroyed (even if you call delete , nor if you follow my suggestion to use a smart pointer). In your case, since you instantiate subclasses ( SubBase ) and store pointers to the parent class ( Base ), you would necessarily need to declare the Base destructor to be virtual :

template <class T>
class Base {
private:
 int I,a,b,c;
public :
  Base(int,int,int,int);
  virtual ~Base() {}
};
    
11.11.2014 / 21:18