How to create an object with class template?

Asked

Viewed 1,169 times

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 I’m giving that error message? It’s that it gives me that message and gives me error in the vector include.

I don’t understand why you won’t let me create this object:

Base < T > * b = new subbase < T > ( int , int , int );
  • 4

    C++ exercising their profession with pride and ugliness.

  • Please put the full error message.

  • Assuming you are calling "Base < T > * b = new subbase < T > ( int , int );" within main, what is the type of T ?

  • The error message is much bigger than the one you sent. I suggest you copy everything, including the code (which the way you did, I can’t try to compile here).

1 answer

4

There’s so much error in your code that it’s hard to know where to start.

First of all, you didn’t put in the original code, nor the original error message. When you edited the code to put it here, you probably inserted a lot of other errors. Hence I don’t know if the errors I see are the original ones or the ones inserted in the edition. For example, most likely you renamed your class Depositos for Base when posting, but forgot to update the SubBase, but you can’t be sure where that came from Depositos without seeing the original code.

That being said, your use of templates doesn’t make any sense, because no time you use or instance type T variables. You wouldn’t happen 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);
};

Then it makes more sense to use a template, but I would need to change more things to work... anyway, I took the pieces of code you posted, put it all together in a single file, and I was modifying until compiling. Stayed 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 declaration of the classes. 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 was 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 builder who picks up 4 ints, but was not passing any value to them. In my version, I pass the same parameters as the function createSubBase takes, plus 42 as last parameter.

You did the same thing on this line here:

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

that is, instead of passing the proper parameters, wrote int in place of each of them (not to mention who wrote Depositos instead of Base). My equivalent was 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 (its had reticence in place of the content, this certainly does not compile, but it is certainly an edition of its before posting).

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

Warehouse<Base<int>> arm;

in the previous version of C++, this code is invalid, and should have a gap between the two signals 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 -o Warehouse Warehouse.cpp

or, in the compiler of WILDEBEEST:

$ g++ -Std=c++11 -o Warehouse Warehouse.cpp

This command -std=c++11 only makes it necessary for you not to give space between the two > at the end of the template instantiation.

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 don’t use the template value for anything. That’s why the code compiles. The Warehouse instantiated in the following line:

`Warehouse<Base<int>> arm;`

you’ll have your kind T = Base<int>, therefore the vector internal to it will be of the 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 at the end of the day, inside Base, type T is not used for anything.

A bug is what you call new and allocates memory, but does not call the delete nowhere. You should implement the destroyer of your class, and call delete for all elements of its vector whouse, fail to do so entails a problem called memory leakage.

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

The other bug is that your destructor Base should be virtual, otherwise the object is not correctly destroyed (nor if you call delete, nor if you follow my suggestion to use a smart pointer). In your case, as you instance subclasses (SubBase) and stores in pointers for the parent class (Base), you would need to necessarily 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() {}
};

Browser other questions tagged

You are not signed in. Login or sign up in order to post.