-1

So I am just trying to make an array of objects of my custom class bcLED and I am getting the error. error: no match for 'operator=' (operand types are 'bcLed' and 'bcLed*')

Can some one tell me why? I know it will be something simple.

also why i am here is there a way to create an array of an unspecified length in C++ and then just append it with an new row each time I want to add an object to it?

void PopulateLEDS(){
    int i;
    bcLed ledArr[17];
    for (i = 0; i< 16; i++)
    {
       ledArr[i] = new bcLed();
       ledArr[i].id = i;
       ledArr[i].charge = 0;
    }
}

OK so i need more help

To avoided creating ten thousand posts I am going to paste the main body of the code so that to see where I am tripping up with the C++ syntax.

the lattest errors are

/Users/bencawley/Documents/Arduino/Test/Bens_Lights/Bens_Lights.ino: In function 'void PopulateLEDS()':
Bens_Lights:49: error: expected primary-expression before 'public'
     public:bcLed ledArr[17];
     ^
Bens_Lights:52: error: 'ledArr' was not declared in this scope
        ledArr[i].id = i;
        ^
/Users/bencawley/Documents/Arduino/Test/Bens_Lights/Bens_Lights.ino: In function 'void BensPattern(uint8_t)':
Bens_Lights:69: error: 'ledArr' was not declared in this scope
       strip.setPixelColor(i,0, 0, ledArr[i].charge, 0);
                                   ^
Using library Adafruit_NeoPixel at version 1.0.6 in folder: /Users/bencawley/Documents/Arduino/libraries/Adafruit_NeoPixel 
exit status 1
expected primary-expression before 'public'

And my code is:

class bcLed{
    public:int id;
    public:int charge;

    void incCharge(int amt)
    {
        charge = charge+amt;
        if(charge >= 255){charge = 255;}
    }
};

void setup() {
  strip.begin();
  strip.show(); // Initialize all pixels to 'off'

  PopulateLEDS();
}

void loop() {
  // Some example procedures showing how to display to the pixels:
  BensPattern(45);

}

void PopulateLEDS(){
    int i;
    bcLed ledArr[17];
    for (i = 0; i< 17; i++)
    {
       ledArr[i].id = i;
       ledArr[i].charge = 0;
    }
}

void BensPattern(uint8_t wait) 
{
    uint16_t i, j;
    int rn = rand() % strip.numPixels() ;

    for (i = 0; i<strip.numPixels(); i++)
    {
      strip.setPixelColor(i,0, 0, 0, 0);
    }

    for (i = 0; i<rn; i++)
    {
      strip.setPixelColor(i,0, 0, ledArr[i].charge, 0);
      ledArr[i].incCharge(1);
    }

      strip.show();
      delay(wait);
}
skyzzle
  • 167
  • 1
  • 4
  • 16
  • 5
    Do you come from a Java background, by any chance? – StoryTeller - Unslander Monica Nov 01 '16 at 09:34
  • 1
    You have an array of 17 `bcLed`. You're attempting to assign a `bcLed*`. Unless you've defined a `operator=` overload for `bcLed` that takes a right-side of `bcLed*`, that isn't going to work (and you probably don't want it to anyway). You don't need that assignment statement *at all*. You already have 17 `bcLed` objects. – WhozCraig Nov 01 '16 at 09:34
  • `ledArr[i]` is `bcLed`. `new bcLed()` returns `bcLed*` – zvone Nov 01 '16 at 09:35
  • 3
    [std::vector](http://en.cppreference.com/w/cpp/container/vector) – bolov Nov 01 '16 at 09:36
  • 1
    Anyway, *"a way to create an array of an unspecified length in C++"* is using [`vector`](http://www.cplusplus.com/reference/vector/vector/) instead of an array. – zvone Nov 01 '16 at 09:37
  • Something java developers tend to forget when they come to C++, you have no good reason, most of the time, to use `new` (and when you do, use `delete` and `delete[]` for arrays). You don't need it here, and for dynamic memory allocation, use C++11's smart pointers. – asu Nov 01 '16 at 09:40
  • To all those who are asking do i come from java the answer is no. I come from python and unity's C# The only time ive ever used java was for mine craft server plugins. – skyzzle Nov 01 '16 at 09:45
  • Same thing goes for those langauges, `new` is always used to instantiate a new reference type. And it's cleaned up for you afterwards by the Garbage Collector. C++ doesn't offers that and just offer automatic allocation. – Hatted Rooster Nov 01 '16 at 09:48
  • @SkylineGodzilla They are trying to understand why you would use the `new` keyword, which I believe means pretty much the same thing and is used in pretty much the same way in both C# and Java. Not so in C++ and I think most people would discourage you from using it, which is probably correct. – George Nov 01 '16 at 09:50
  • So what I understand is in C++ there is no need to use new to assign an new object to anything. And here i thought C++ was going to be like C# :p – skyzzle Nov 01 '16 at 09:56
  • @SkylineGodzilla, I asked because it's a mistake I often see made by devs with Java/C# backgrounds. If you want to be proficient in C++, you need to learn it like a novice programmer. Despite the somewhat similar syntax, its night & day compared to C#/Java in terms of programming idioms. – StoryTeller - Unslander Monica Nov 01 '16 at 10:02

2 Answers2

3

new isn't always needed in C++, and definitely not here. new allocates dynamic memory for you if automatic allocation isn't good enough for you. You usually only use new if you want the variable to outlive it's scope. Memory allocated with new must also always be deleted in order to avoid a memory leak. In modern C++, the use of new is even less needed because we have smart pointers.

bcLed ledArr[17];

This already creates 17 bcLeds for you (like how you would use new in C#, requires no cleanup), no need to use new on them. Just work with them.. Your loop condition is wrong too, it's supposed to be < 17.

for (i = 0; i < 17; i++)
{
   ledArr[i].id = i;
   ledArr[i].charge = 0;
}

also why i am here is there a way to create an array of an unspecified length in C++ and then just append it with an new row each time I want to add an object to it?

Yes, that's what a std::vector is for:

#include <vector>
std::vector<bcLed> ledArr(17);

//loop over them:
for(int i = 0; i < ledArr.size(); ++i)
{
  //ledArr[i]
}

//or:
for(std::vector<bcLed>::iterator itr = ledArr.begin() itr != ledArr.end(); ++itr)
{
  //*itr
}

// to insert to the back of the vector use push_back:

bcLed aLed;
ledArr.push_back(aLed);

If you have access to C++11 you can use a range based loop instead and use emplace_back:

#include <vector>
std::vector<bcLed> ledArr(17);

//loop over them, just to iterate:
for(const auto& led : ledArr)
{
  //led.id
  //led.charge
}

//appending to the vector:

ledArr.emplace_back(/*constructor arguments*/);

To answer your comment

ok im going to brave and ask this when you say "if you want the variable to outlive it's scope or you're working with low level memory" I don't understand what any of that means... well mostly I don't understand what you mean by scope or low level memory. Could you explain those? is scope the time that the method runs for?

A scope of a variable is the context in which it is defined. Automatic storage lives until the end of it's scope. Braces { } indicate scope. For example:

void foo()
{
  int x;
  bcLed aLed;
  { //create a new inner scope
    bcLed innerLed;   
  } //scope ends, all automatic variables are destroyed (innerLed in this case)

  //can't use `innerLed` here.

  int new_int = x; 
} // scope ends, same goes, new_int, x, aLed are destroyed.

Really though, a good book will tell you the differences and when they should be used.

Community
  • 1
  • 1
Hatted Rooster
  • 35,759
  • 6
  • 62
  • 122
  • Also consider `emplace_back` to construct elements in-place in C++11. – asu Nov 01 '16 at 09:43
  • ok im going to brave and ask this when you say "if you want the variable to outlive it's scope or you're working with low level memory" I don't understand what any of that means... well mostly I don't understand what you mean by scope or low level memory. Could you explain those? is scope the time that the method runs for? – skyzzle Nov 01 '16 at 09:52
  • @SkylineGodzilla : See the page about [object/reference](http://en.cppreference.com/w/cpp/language/lifetime) lifetimes on cppreference. – asu Nov 01 '16 at 09:56
  • The "low level memory" part seems a bit awkward to me though, but I get what he means. As for the lifetime, imagine `int* a; { int b; a = &b; }` - this will produce undefined behavior, because b is supposed to be destroyed at the end of the scope. So you have to do `int* a; { a = new int(); } delete a;`. And using a unique_ptr, that will destroy its content itself: `std::unique_ptr a; { a = std::make_unique(); }`. – asu Nov 01 '16 at 09:58
  • @SkylineGodzilla updated my answer. I left out the low level memory part because I feel that's not in the scope of this question. Asu did a good job of explaining it though. – Hatted Rooster Nov 01 '16 at 10:01
1

ledArr[i] = new bcLed(); doesn't work, as the error message said, you can't assign an pointer to bcLed (i.e. bcLed*) to a bcLed.

For bcLed ledArr[17];, the 17 elements of array has been default constructed; You don't need to new one at all. So just remove the code causing errors, the following code would work fine.

bcLed ledArr[17];
for (i = 0; i < 16; i++)
{
   ledArr[i].id = i;
   ledArr[i].charge = 0;
}

is there a way to create an array of an unspecified length in C++ and then just append it with an new row each time I want to add an object to it?

That's what std::vector supposed to do.


If you want to process all the elements of the array, the condition of for should be i < 17.

songyuanyao
  • 169,198
  • 16
  • 310
  • 405