0
\$\begingroup\$

I’m making a 2d top down shooter game and I was working on shooting bullets. Im using a vector for the bullet in my player class: std::vector b; And I have coded a shoot function which shoots the bullet and deletes it if it is out of the screen:

void Player::shoot(float timer)
{
//Getting Key Press
if (Keyboard::isKeyPressed(Keyboard::Space))
{
    space = true;
}
else
{
    space = false;
}

Bullet b1;
b.push_back(Bullet(b1));

if (space)
{
    for (int i = 0; i < b.size(); i++)
    {
        b[i].setPos(pos);
    }

}
else
{
    for (int i = 0; i < b.size(); i++)
    {
        b[i].update(true);
        if (b[i].getPos().y < 0.0f)
        {
            b.erase(b.begin() + i);
            i--;
        }
    }
}   
}

But I have encountered an error: Error C2280 'Bullet &Bullet::operator =(const Bullet &)': attempting to reference a deleted function

I don’t understand why this is happening can someone explain? Here is the bullet class Header:

#pragma once
#include <SFML/Graphics.hpp>

using namespace sf;

class Bullet
{
private:
Texture t;
Sprite bullet;
Vector2f pos;
public:
Bullet();
~Bullet();
void setPos(Vector2f pos);
void move(bool up);
Sprite getSprite();
Vector2f getPos();
};

Cpp file: #include "stdafx.h" #include "Bullet.h"

Bullet::Bullet()
{
//Setting Texture
t.loadFromFile("Graphics/bullet.png");
bullet.setTexture(t);

}

Bullet::~Bullet()
{
}

void Bullet::setPos(Vector2f pos)
{

//Setting Position
this->pos = pos;
bullet.setPosition(this->pos);
}

void Bullet::move(bool up)
{
if (up)
{
    bullet.move(0.0f, -10.0f);
}
else
{
    //TODO
}
}

Sprite Bullet::getSprite()
{
return bullet;
}

Vector2f Bullet::getPos()
{
return pos;
}
\$\endgroup\$
  • \$\begingroup\$ As a side question, is this your actual code, or did you assemble the relevant pieces of it to create a good question? \$\endgroup\$ – Vaillancourt Sep 27 '18 at 18:33
  • \$\begingroup\$ @AlexandreVaillancourt Thanks for the help. I'll try and see if this works. And Yes I have only assembled the relevant pieces of my code. \$\endgroup\$ – Arsh Panesar Sep 28 '18 at 14:07
  • \$\begingroup\$ How do I iterate through a vector of pointers? I want to access a function from the bullet class but I don't know how to do it. \$\endgroup\$ – Arsh Panesar Sep 28 '18 at 15:24
  • \$\begingroup\$ Here is the loop: \$\endgroup\$ – Arsh Panesar Sep 28 '18 at 15:24
  • \$\begingroup\$ for (auto it = b.begin(); it != b.end(); it++) { //How to call a function here } \$\endgroup\$ – Arsh Panesar Sep 28 '18 at 15:25
2
\$\begingroup\$

I'm going out of my usual path here with the more 'technical' c++ rules, so if there are anything wrong here, please point it out. Also, this is only based on what I understand from the provided code, the code from SFML and from knowledge available on the internet.


Why do you get this error?

According to a popular site,

Deleted implicitly-declared copy assignment operator

A defaulted copy assignment operator for class T is defined as deleted if any of the following is true:

  • T has a non-static data member of non-class type (or array thereof) that is const;

  • ...

  • T has a non-static data member or a direct or virtual base class that cannot be copy-assigned (overload resolution for the copy assignment fails, or selects a deleted or inaccessible function);

(Emphasis mine.)

Looking at your Bullet, it does not appear like there are any issues there, but we have to look at what it's using.

Apparently, the Sprite class that you're using is having a const Texture* which prevents it from being implicitly copy-assigned (i.e. the first bullet point).

The error you get is from the last bullet point in that quote: your Bullet class has not received an automatically copy-assignment operator because some of the classes that it uses has not received one.

C++ is great!! Although it's the greatest tool to shoot yourself in the foot, it's getting more and more 'new user friendly'!

It's preventing you from doing something you might not be aware you're doing.

How do you fix this error?

I presume b is declared like this:

std::vector<Bullet> b;

I don't think you really intend to copy your object around.

Instead, use a vector of pointers to bullets:

std::vector<std::unique_ptr<Bullet>> b;

This way, the vector will most likely move the references instead of copying them.


Now you're having other issues with this code.

for (int i = 0; i < b.size(); i++)
{
    b[i].update(true);
    if (b[i].getPos().y < 0.0f)
    {
        b.erase(b.begin() + i);
        i--;
    }
}

Every time you modify a vector when you iterate over it like, [insert you favourite god(s) vs kitten quote here]. It not only makes the code hard to read, it opens up the door to shooting you in the foot.

Alternative ways are to use a while and an iterator, or better, use the remove_if function (see this answer on SO).

\$\endgroup\$
1
\$\begingroup\$

T of std::vector<T> must be move-assignable to call erase().

That means T needs to have either a move assignment operator or a copy assignment operator defined. Your Bullet class has neither, and thus cannot be move-assigned as needed by the vector implementation, and thus you get this error.

You should define a copy assignment (or move assignment, but I'd suggest you start with copy assignment) operator in Bullet to fix this.

\$\endgroup\$

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.