Declaring a vector array (custom type) in a class, then initializing on creation

I'm having a rather large problem being able to pre-declare a vector array of a private type, then initializing that array somewhere in a ".cpp" file.

In order for it to let me declare something I had to make the array hold an address for that type:
std::vector< TileSprite >& tileSprite;

Then in the constructor for the class:
tileSprite();

I have no idea how to initialize a vector array element, let alone the array itself.

Full Code:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
//Attributes.h
class Attributes
{
   private:
   struct TileSprite
   {
      std::string name;
      std::string file;
      unsigned short index;
   };

   public:
   std::vector< TileSprite* > tileSprite;
}

//Attributes.cpp
Attributes::Attributes(void)
{
   std::vector< TileSprite > tileSprite; //It's this bit which is confusing me
}
Last edited on
1
2
   public:
   std::vector< TileSprite >& tileSprite;


tileSprite is a reference to a vector not a function.
Class members that are references have to be initialised in the initialization list.

So this tileSprite(); at line 19 is not right.


Krisando wrote:
In order for it to let me declare something I had to make the array hold an address for that type:

std::vector< TileSprite >& tileSprite;


That doesn't actually give you a vector holding the address of the type TileSprite. If creates a reference to a vector of TileSprites.

You would need this:

std::vector< TileSprite* > tileSprite;

If you want to call a non-default constructor you need to do that in the ctor-initializor:

1
2
3
4
Attributes::Attributes(void)
: tileSprite()
{
}
Wow thanks for that non-standard constructor, that solved another problem I would have had.

I've now done as you said
std::vector< TileSprite* > tileSprite;

How do I initialize this vector:
std::vector< TileSprite > tileSprite;
Last edited on
What do you mean, non-standard constructor? You initialize it however you want. The default constructor for vector creates a vector with size = capacity = 0. You can specify whatever size you want and create a container of null pointers. I've no idea when you plan on constructing the tileSprite objects or what your requirements for that are. When you are ready to put actually objects into the vector you use operator[] or one of the insertion member functions. It depends on whether you construct it to be empty or with some number of null pointers. I'm sure that there are many ways to do it. Read the vector documentation and determine the best way for your situation. The actual insertion of data into the container can be done anywhere within the class that you want. I do not know what your TileSprite type is so I have shown a default constructor. You'd obviously have to call whichever constructor is appropriate.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
Attributes::Attributes(void)
: tileSprite()
{

   // tileSprite is empty
   tileSprite.push_back(new TileSprite());  // do it as many times as you like
}

// or
Attributes::Attributes(void)
: tileSprite(10) // 10 zero initialized pointers
{

   // tileSprite is empty
   for(int i = 0; i < tileSprite.size(); i++)
   {
      tileSprite[i] = new TileSprite();  // construct 10 objects and copy the pointers
   }
}
Last edited on
=\ Not sure if that initializing is related, I don't know the specific terms but I need to initialized the variable.

Header .h:
std::vector< TileSprite* > tileSprite;

Somewhere in .cpp:
std::vector< TileSprite > tileSprite; //It's this bit which is confusing me

How can I allow it to hold instances "TileSprite".
You mean in the .h since it is a class attribute?
1
2
std::vector< TileSprite > tileSprite; // holds instances of TileSprite
std::vector< TileSprite* > tileSprite; // holds pointers to instances of TileSprite which you must manage with new and delete 


All vectors are constructed in the same way. They are templates so the difference is in how you insert the elements. If you want pointers you insert pointers. If you want objects you insert using a temp object and let vector do the copying for you. Beyond that I am not sure what else you need help with.
Krisando wrote:
How can I allow it to hold instances "TileSprite".


You use push_back(). Actually I don't think you need to store pointers in your vector. You could do this:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
//Attributes.h
class Attributes
{
   private:
   struct TileSprite
   {
      std::string name;
      std::string file;
      unsigned short index;
   public:
      // Constructor to set values of new TileSprites
      TileSprite(std::string name, std::string file, unsigned short index)
      : name(name), file(file), index(index)
      {
      }
   };

   public:
   std::vector< TileSprite > tileSprite;
}

//Attributes.cpp
Attributes::Attributes(void)
{
   tileSprite.push_back(TileSprite("floor", "data/floor.jpg", 1));
   tileSprite.push_back(TileSprite("wall", "data/wall.jpg", 2));
   tileSprite.push_back(TileSprite("ceiling", "data/ceiling.jpg", 3));
}
Last edited on
Wow, thankyou very much! The power of C++ surprises me.

Is there any difference between doing TileSprite() and new TileSprite()? Or does it return a pointer, I think previously using C# has really mixed things up for me.

Also does the ":" operator have other uses besides allowing a private value be set by a local?
1
2
3
4
5
6
7
TileSprite(std::string name)
: name(name)
{

};

TileSprite() {};
Yes, new TileSprite(); does return a pointer.

The colon separates the constructor signature from the ctor-initializor list. That is where member variables are initialised (whether private or public).

1
2
3
4
5
6
7
8
9
10
class MyType
{
    int i;
    std::string s;

private:
    MyType() : i(2), s("hello") // list of initializers after the colon ';'
    {
    }
};
Last edited on
Topic archived. No new replies allowed.