Меню

Ошибка invalid use of non static data member

For a code like this:

class foo {
  protected:
    int a;
  public:
    class bar {
      public:
        int getA() {return a;}   // ERROR
    };
    foo()
      : a (p->param)
};

I get this error:

 invalid use of non-static data member 'foo::a'

currently the variable a is initialized in the constructor of foo.

if I make it static, then it says:

 error: 'int foo::a' is a static data member; it can only be initialized at its definition

However I want to pass a value to a in the constructor.
What is the solution then?

Alecs's user avatar

Alecs

2,2168 gold badges32 silver badges45 bronze badges

asked Mar 6, 2012 at 19:11

mahmood's user avatar

2

In C++, unlike (say) Java, an instance of a nested class doesn’t intrinsically belong to any instance of the enclosing class. So bar::getA doesn’t have any specific instance of foo whose a it can be returning. I’m guessing that what you want is something like:

    class bar {
      private:
        foo * const owner;
      public:
        bar(foo & owner) : owner(&owner) { }
        int getA() {return owner->a;}
    };

But even for this you may have to make some changes, because in versions of C++ before C++11, unlike (again, say) Java, a nested class has no special access to its enclosing class, so it can’t see the protected member a. This will depend on your compiler version. (Hat-tip to Ken Wayne VanderLinde for pointing out that C++11 has changed this.)

answered Mar 6, 2012 at 19:17

ruakh's user avatar

ruakhruakh

172k26 gold badges266 silver badges302 bronze badges

6

In C++, nested classes are not connected to any instance of the outer class. If you want bar to access non-static members of foo, then bar needs to have access to an instance of foo. Maybe something like:

class bar {
  public:
    int getA(foo & f ) {return foo.a;}
};

Or maybe

class bar {
  private:
    foo & f;

  public:
    bar(foo & g)
    : f(g)
    {
    }

    int getA() { return f.a; }
};

In any case, you need to explicitly make sure you have access to an instance of foo.

answered Mar 6, 2012 at 19:16

Ken Wayne VanderLinde's user avatar

The nested class doesn’t know about the outer class, and protected doesn’t help. You’ll have to pass some actual reference to objects of the nested class type. You could store a foo*, but perhaps a reference to the integer is enough:

class Outer
{
    int n;

public:
    class Inner
    {
        int & a;
    public:
        Inner(int & b) : a(b) { }
        int & get() { return a; }
    };

    // ...  for example:

    Inner inn;
    Outer() : inn(n) { }
};

Now you can instantiate inner classes like Inner i(n); and call i.get().

answered Mar 6, 2012 at 19:18

Kerrek SB's user avatar

Kerrek SBKerrek SB

457k91 gold badges866 silver badges1073 bronze badges

1

You try to access private member of one class from another. The fact that bar-class is declared within foo-class means that bar in visible only inside foo class, but that is still other class.

And what is p->param?

Actually, it isn’t clear what do you want to do

answered Mar 6, 2012 at 19:17

Alecs's user avatar

AlecsAlecs

2,2168 gold badges32 silver badges45 bronze badges

4

Your Question is not clear but there is use case when you will get this issue .

Invalid use of non-static data member.

When you are using «non-static data member in another class try to not use with scope resolution operator
Example::className::memberData = assignivalue ;
instead of above try to use object of className class;
Example:: m_pClassName->memberData=assignValue;*

answered Dec 5, 2022 at 13:00

Ramanand Yadav's user avatar

class Stack
{               
private:

    int tos;
    const int max = 10;    
    int a[max];
public:

    void push(int adddata);
    void pop();
    void printlist();
};

error: invalid use of non-static data member ‘max’

whats wrong in the code, and please help me with proper correction.
Thankyou

Jim Lewis's user avatar

Jim Lewis

42.9k7 gold badges85 silver badges96 bronze badges

asked Apr 19, 2015 at 18:32

user3584564's user avatar

It is mandatory that the array size be known during compile time for non-heap allocation (not using new to allocate memory).

If you are using C++11, constexpr is a good keyword to know, which is specifically designed for this purpose. [Edit: As pointed out by @bornfree in comments, it still needs to be static]

static constexpr int max = 10;

So, use static to make it a compile time constant as others have pointed out.

answered Apr 19, 2015 at 18:49

Titus's user avatar

TitusTitus

8978 silver badges18 bronze badges

2

As the error says, max is a non-static member of Stack; so you can only access it as part of a Stack object. You are trying to access it as if it were a static member, which exists independently of any objects.

Hence you need to make it static.

static const int max = 10;

If the initialization is in the header file then each file that includes the header file will have a definition of the static member. Thus during the link phase you will get linker errors as the code to initialize the variable will be defined in multiple source files.

answered Apr 19, 2015 at 18:43

Vinay Shukla's user avatar

Vinay ShuklaVinay Shukla

1,80813 silver badges39 bronze badges

As the compiler says make the data member static

static const int max = 10;    

answered Apr 19, 2015 at 18:35

Vlad from Moscow's user avatar

Vlad from MoscowVlad from Moscow

286k23 gold badges178 silver badges322 bronze badges

You need to make max a compile time constant:

static const int max = 10;

answered Apr 19, 2015 at 18:35

Johan Lundberg's user avatar

Johan LundbergJohan Lundberg

25.7k12 gold badges71 silver badges97 bronze badges

3

The Conceptual mistake that you are making is that you are trying to initialize values for the class in the class definition .This is the reason why constructors exist .Using a parametrized constructor set values of top of stack and its size.
When making the stack object pass the size of the stack to be created:

class Stack {               
private:
  int tos; 
  int a[max];

public:
  Stack(int s);
  void push(int adddata);
  void pop();
  void printlist();
};

Stack::Stack(int s) {
  tos=-1;
  max=s;
}

gudok's user avatar

gudok

3,9292 gold badges20 silver badges30 bronze badges

answered Feb 18, 2017 at 6:36

Anchellon's user avatar

Цитата
Сообщение от Lyosha12
Посмотреть сообщение

Вопрос мой тот же: почему? Ограничения какого механизма не позволяют это сделать?

Аргументы по умолчанию — это именно агрументы. Они вычисляются и подставляются в вызов функции именно в контексте вызывающего кода.

Например (отвлечемся пока от указания полей), рассмотрим такую попытку

C++
1
void foo(int a, int b = a);

В данном случае мы пытаемся использовать параметр функции в качестве умолчательного аргумента для другого параметра. Возникает вопрос, как это должно работать при вызове foo(rand())? Это должно транслироваться в два вызова rand()?

Это, скорее всего плохая идея. Скорее всего мы ходим, чтобы rand() вызывался только один раз,

C++
1
2
int tmp;
foo(tmp = rand(), tmp);

Но это уже накладывает требования на порядок вычисления аргументов: первый аргумент должен вычисляться первым. А в С++ порядок вычисления аргументов никогда не фиксировался и не гарантировался.

То есть такая фича потребует существенной переработки гарантий, даваемых языком С++, в процессе которой вскроется еще масса подводных камней. Вышеприведенное объявление foo не скомпилируется — параметры функции нельзя использовать в качестве умолчательных аргументов для других параметров.

А ваша ситуация фактически полностью аналогична этой, если вспомнить, что this — это фактически просто скрытый параметр функции-члена класса. То есть вы пытаетесь сделать вот что

C++
1
2
Node* findResource(Graph *this, string const& wantedNode, Node* current = this->head)
//                        ^^^^ - скрытый параметр

То есть ваш умолчательный аргумент зависит от первого параметра функции. По вышеописанным причинам этого не допускается.

To start with, I’m running windows 8 with Code::Blocks 12.11.

My main goal is to create a class named SCREEN with a member Array[][] and have this Array being modified and sending data to nested classes ‘Trim’ and ‘ScreenClass’.

To make my goal better understood, this could be achieved in another way: same class ‘SCREEN’ containing DIRECLTY all the functions contained in ‘Trim’ and ‘ScreenClass’, without these two classes ever being created.
BUT in those too classes, ‘Trim’ and ‘ScreenArray’, I will input MUCH code, MUCH functions and I don’t want them to be RAW in the ‘SCREEN’ class as finding each function then, would be a real trouble!! (I tried commenting like
//=========================================================
or 2 times the above, or even with asterisks (*) but when a lot of functions gather it’s getting baaaaad.)

To start visualizing it, I want something like 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
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
class SCREEN
{
private:
    char Array[160][160];//[x],[y]
    int CurrentWidth;
    
    class ScreenClass
    {
    private:
        void Initialize()
        {
            Array[x][y]=' '; //This refers to SCREEN::Array
        }
    public:
        bool Set(int x,int y)
        {
            CurrentWidth=10; //This refers to SCREEN::CurrentWidth
            Array[x][y]=' '; //This refers to SCREEN::Array
        }
        char Get(int x,int y) 
        {
            return Array[x][y]; //This refers to SCREEN::Array
        }

        ScreenClass(){Initialize();}

    };
    ScreenClass ScreenArray;


    class TrimClass 
    {//... Like ScreenClass. If I complete correctly ScreenClass, I will complete correctly this too 
        
        void Clean()
        {
            Array[1][1]=' '; //This refers to SCREEN::Array
        }
    };
    TrimClass Trim;

    // --other Functions--


public:
    
    void Clean (char Background=' ')
    {
        ScreenArray.Set(x,y);
    }
    void CleanTrim (char Background=' ') //NOTE: Here after trim class
    {
        Trim.Clean(Background);
    }
    void CleanAll (char Background=' ')
    {
        CleanTrim(Background);
        Clean(Background);
    }

    
    // --other Functions--

    SCREEN()
    {
        
    }
};

Which is basiclly and my code….

I want to use it in the end like:

1
2
3
4
5
6
7
8
9
int main()
{
    SCREEN Screen;
    Screen.Clean();
    //or
    Screen.Trim.Clean();
}

So I don’t want to use any kind of static data..

I keep getting this error: invalid use of non-static data member ‘SCREEN::X’
where X is Array, CurrentWidth and other data of SCREEN.

I tried googling something like ‘nested classses error invalid use of non-static data member’ among other but wthout resault.

I know that in order to use anything from ScreenClass I have to create an Object of ScreenClass (which can obviousy be seen in my code xD), but what I also learned is that a class declared and defined within an enclosing class, is not a UNIQUE property of the enclosing-class…

Therefore Trim (of type TrimClass) and ScreenArray (of type ScreenClass) coud have been created and outside of SCREEN (altough their class was defined within SCREEN) and that is why they dont know which object of SCREEN they must use the data from.

Well I want EACH object of type ‘SCREEN’ to have it’s VERY OWN set of ‘Trim’ and ‘ScreenArray’ objects. To give an example:

1
2
3
4
class AClass
{
   int a;
}

In my exaple Each object of type AClass has it’s very OWN integer ‘a’, therefore a coding line of a=’something’, would never send an error implying that ‘a’ doesn’t know which object of AClass to edit ‘a’ from…. lol

Thanks in advance for any help 🙂

Extra info:

What I HAVE tried:

changing this

1
2
3
4
5
6
7
8
9
10
11
12
    class ScreenClass
    {
    private:
        void Initialize()
        {
            Array[x][y]=' '; //This refers to SCREEN::Array
        }
        //...
        ScreenClass(){Initialize();}

    };
    ScreenClass ScreenArray();

to this:

1
2
3
4
5
6
7
8
9
10
11
12
    class ScreenClass
    {
    private:
        void Initialize(SCREEN * const SCREENthis)
        {
            Array[x][y]=' '; //This refers to SCREEN::Array
        }
        //...
        ScreenClass(SCREEN * const SCREENthis){Initialize(SCREENthis);}

    };
    ScreenClass ScreenArray(this);

and all was fine…. except the last line ‘ScreenClass ScreenArray(this);’ where I got the error: expected identifier before ‘this’, and for the same line another error (or different aproach?): expected ‘,’ or ‘…’ before ‘this’

P.S.:
If that will help at all, my problem IN ABSTRACT is (in my point of view)

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
class A
{
private/public/protected: (any of the three)
    //many data, from now on reffered to as A::Data.
private/public/protected:
    class B
    {
        void BFunction()
        {
            //Change A::data
        }
    }
    B b;
    
    void AFunction()
    {
        b.f();
    }
}

int main()
{
    A a;
    a.AFunction();

}

The member Trim of object Screen does not know that it is a member of that particular SCREEN object and therefore it does not know which Array to reference.

Each TrimClass object could have a pointer to its parent.

How? 😀 hahaha
I have no idea how to do this^^

Let’s say I add one «SCREEN* ScreenPtr» within ScreenClass….
Do I initiate it? Do I give it a value? Where? With what code?

And thanks for telling me that. I didn’t knew 🙂
Thanks a lot!

Last edited on

I didn’t see your addendum while posting. You were almost there.

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
29
class A
{
  struct B
  {
    A * parent;

    B( A * p )
    : parent( p )
    {}

    void f()
    {
      cout << parent->data;
    }
  };

  int Data;
  B b;
    
public:
  A ()
  : Data( 42 ), b( this )
  {}

  void AFunction()
  {
    b.f();
  }
}

Last edited on

The Trim object is private, and therefore will not be able to be accessed from there(main).

Aceix.

Ok, REALY GOOD 😀
but .. here are some questions: (xD)

In line 3: Why struct and not class?? O.o

In lines 7-8, 21-22: can I rewrite these this way-> «B(A*p) {parent = p;}», » A() {Data=42; b = this;}» ???? 😀

It would help me A LOT (the way you wrote it gives me a headache to translate to something I understand 😐 .Nothing personal, Im talking about the so called «»Member initialization in constructors», if that is the correct name).

Another one. I have seen that before and I wοndered again about it,
in line 13: you reffer to «Data» while «Data» is FIRST time mentionedat line 17!! O.O
XD excuse my enthusiasm about this but I am new in programming and I don’t quite understand this, not yet :d

Thanks for the code! 😀
I’ll go try it!

I’ll come back with the resaults 😀

Again, thank you!

Line 3: unimportant. Use what you need.

The constructors. See member initializer list http://en.cppreference.com/w/cpp/language/initializer_list

Line 13. My mistake (twice). We can write the implementation later:

1
2
3
4
5
6
7
8
9
10
class A {
  class B {
    void f();
  };
  int Data;
};

void A::B::f() {
  cout << parent->Data;
}

HOOOOOOOOOOOOOOOOOLY SH…….!!!!!! (You know the rest of the word! 😀 😀 😀 😀 😀 😀 😀 I’m gonna throw a party!! 😀 😀 😀 😀 😀 😀 WOOOOOHOOOOOOO!!!!

I run a test on a minimalistic version of the program and I get no errors! 😀

It must have worked!! (though I’m quite tired to try on the real program, it’s 1:47 the late night right now here X| and I’m about to go to sleep)

I did ALL you said with an exception,
I didn’t use struct but i used class (as mentioned in my question before)
and one HUGE note. When Initializing A like this: A(){b=this} I get an error.
When I do it like you said: A():b(this) {} I don’t!! (*rubbing my eyes to see clearer).

I mean what the he*k!?!?!?! Isn’t it the same?
Just a different methode for initializing?? O.o
Any hint for what should I read to understand the difference?
I read this topic* about it and thought/understood that this: A(){b=this} and A():b(this){} would be the same. *Topic: http://www.cplusplus.com/doc/tutorial/classes/

And I don’t understand how the code in line 18 of your last code (as I see it 1:07 AM) works…. I mean it’s constructor needs 1 parameter. An A* .. how can I say «B b;» ?
I guess that A():b(this) {} is involved.. But how? O.O

Again REEEEEALLY THANK YOU! 😀 You’re the MAN! :)))))

@Aceix, thank you for your reply too 🙂
keskiverto was faster, problem solved! 😀

Last edited on

I will see you tommorow. For today, have a good night (if it is night where you are right now) or a good day 🙂

…zZzZzZzZzZzZzZ (Necro is Fast asleep xD)

Hey, really sorry for not replying this long. I run into some troubles and I couldn’t continue with the program.
Right now I just got curious if I shall change the way my program is structured.. xD

I mean, if I go the way I am already up to, I have 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
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
class SCREEN
{
        class ScreenClass
        {
                //...blah-blah...
                //....some more...

                ScreenClass(SCREEN* const ParentSCREEN)
        }
        ScreenClass ScreenArray;

        class TrimClass
        {
                class UpperTrim()
                {
                        //...blah-blah....
                        //this "blah-blah" above though requires a SCREEN and a ScreenClass....
                   Upper(SCREEN* const ParentSCREEN, ScreenClass* const ParentScreenClass)
                }
                UpperTrim Upper();
                class LowerTrim() //Almost same code with UpperTrim
                {} LowerTrim Lower;
                //.. Left, right and Corners classes as well.

                //And corners class is like THAT
                class CornersTrim
                {
                        class UpperRightCorner
                        {


                                UpperRight(ScREEN* const ParentSCREEN)
                        }
                        UpperRightCorner UpperRight;
                        //Same for Lower Right, UperLeft, LowerLeft ....                


                        CornersTrim(SREEN* const ParentSCREEN):UpperRight(ParentSCREEN),UpperLeft(...)//LowerRight and lowerleft
                        {}
                }
                CornersTrim Corners;


                TrimClass(SCREEN* const ParentSCREEN):Upper(ParentSCREEN,this), Lower(ParentSCREEN,this), Left(....), Right(....), Corenrs(....)
                {}
        }

        TrimClass Trim


        SCREEN():ScreenArray(this), Trim(this)
}

And I already guess that this option is not VIABLE! xD
I find this TOOOO much for something that simple.

Should I just imput classes like Trim and ScreenClass in Header files on top of the class SCREEN and use the same methode (all those pointers), or is there a better way?
example:

1
2
3
4
5
6
7
8
#include "Trim.h"
#include "ScreenClass.h"

SCREEN
{
    TrimClass Trim
    //etc
}

The above would put less «strein», and would require less effort to read for the SCREEN class. ( I think..)

I thought of doing this: Instead of creating classes for manipulating the Trim and the Array in my SCREEN class, to just make simple fuctions, and to deal with the large amount of code in a single class, to include in headers the functions of my SCREEN class categorized.

In example:

1
2
3
4
5
6
SCREEN
{
    #include "TrimFunctions.h"
    #include "ArrayFunctions.h"

}

But aren’t wesupposed to only include DECLARATION of CLASSES in headers? O.o

I’m pretty stuck.

Hmmm, another though:

Since my SCREEN is a suplementary class, and not to work on it’s own (well it can, but it is not intended. I want it for other programs) , should I create an easy to see and maintain interface of it at a header SCREEN.h and then just define the functions at a SCREEN.cpp?

Help? 😀
Serioucly, any help apreciated!
I’m new at programming and I can’t say I found my way yet

Last edited on

Вопрос:

Я делаю масштабируемую библиотеку Arduino, но получаю ошибку компилятора: invalid use of non-static data member.

Мой код:
LedCube.h:

#ifndef LedCube_h
#define LedCube_h
#include "Arduino.h"
class LedCube {
private:
int _x, _y, _z;
byte _lPins[_y];
byte _cPins[_z][_x];
public:
LedCube(int x, int y, int z, byte *lPins, byte (*cPins)[_x]);
void displayFrame(bool frame[][_x][_z]);
void displayLayer(int i, bool frame[][_x][_z]);
};
#endif

Ledcube.ino(CPP):

#include "Arduino.h"
#include "LedCube.h"

int _x, _y, _z;
//bool frame[y][z][x] = {0};
byte _lPins[_y];
byte _cPins[_z][_x];

LedCube::LedCube(int x, int y, int z, byte lPins[], byte cPins[][_x]) {
_x = x;
_y = y;
_z = z;
_lPins = lPins;
_cPins = cPins;
}

void LedCube::displayFrame(bool frame[_y][_x][_z]) {
int i;
for(i=0;i<_y;i++) {
displayLayer(i, frame);
pinMode(_lPins[i], OUTPUT);
delay(1);
pinMode(_lPins[i], INPUT);
}
}

void LedCube::displayLayer(int i, bool frame[_y][_x][_z]) {
int j,k;
for(j=0;j<_z;j++) {
for(k=0;k<_x;k++) {
if(frame[i][j][k]) {
digitalWrite(_cPins[j][k], HIGH);
}
else {
digitalWrite(_cPins[j][k], LOW);
}
}
}
}

Я хочу принять переменные x, y и z и установить их в _x, _y и _z в конструкторе и, следовательно, не хотят устанавливать переменные static.
Я использую эти переменные для объявления цикла.

Ошибка, которую я получаю:

Arduino: 1.6.5 (Windows 10), Board: "Arduino/Genuino Mega or Mega 2560, ATmega2560 (Mega 2560)"

In file included from LedCube.ino:2:0:
LedCube.h:12: error: invalid use of non-static data member 'LedCube::_y'
int _x, _y, _z;
^
LedCube.h:13: error: from this location
byte _lPins[_y];
^
LedCube.h:12: error: invalid use of non-static data member 'LedCube::_z'
int _x, _y, _z;
^
LedCube.h:14: error: from this location
byte _cPins[_z][_x];
^
LedCube.h:12: error: invalid use of non-static data member 'LedCube::_x'
int _x, _y, _z;
^
LedCube.h:14: error: from this location
byte _cPins[_z][_x];
^
LedCube.h:12: error: invalid use of non-static data member 'LedCube::_x'
int _x, _y, _z;
^
LedCube.h:16: error: from this location
LedCube(int x, int y, int z, byte *lPins, byte (*cPins)[_x]);
^
LedCube.h:12: error: invalid use of non-static data member 'LedCube::_x'
int _x, _y, _z;
^
LedCube.h:17: error: from this location
void displayFrame(bool frame[][_x][_z]);
^
LedCube.h:12: error: invalid use of non-static data member 'LedCube::_z'
int _x, _y, _z;
^
LedCube.h:17: error: from this location
void displayFrame(bool frame[][_x][_z]);
^
LedCube.h:12: error: invalid use of non-static data member 'LedCube::_x'
int _x, _y, _z;
^
LedCube.h:18: error: from this location
void displayLayer(int i, bool frame[][_x][_z]);
^
LedCube.h:12: error: invalid use of non-static data member 'LedCube::_z'
int _x, _y, _z;
^
LedCube.h:18: error: from this location
void displayLayer(int i, bool frame[][_x][_z]);
^
LedCube:6: error: array bound is not an integer constant before ']' token
LedCube:7: error: array bound is not an integer constant before ']' token
LedCube:7: error: array bound is not an integer constant before ']' token
In file included from LedCube.ino:2:0:
LedCube.h:12: error: invalid use of non-static data member 'LedCube::_x'
int _x, _y, _z;
^
LedCube:9: error: from this location
LedCube.ino: In constructor 'LedCube::LedCube(...)':
LedCube:10: error: 'x' was not declared in this scope
LedCube:11: error: 'y' was not declared in this scope
LedCube:12: error: 'z' was not declared in this scope
LedCube:13: error: '_lPins' was not declared in this scope
LedCube:13: error: 'lPins' was not declared in this scope
LedCube:14: error: '_cPins' was not declared in this scope
LedCube:14: error: 'cPins' was not declared in this scope
In file included from LedCube.ino:2:0:
LedCube.h: At global scope:
LedCube.h:12: error: invalid use of non-static data member 'LedCube::_y'
int _x, _y, _z;
^
LedCube:17: error: from this location
In file included from LedCube.ino:2:0:
LedCube.h:12: error: invalid use of non-static data member 'LedCube::_x'
int _x, _y, _z;
^
LedCube:17: error: from this location
In file included from LedCube.ino:2:0:
LedCube.h:12: error: invalid use of non-static data member 'LedCube::_z'
int _x, _y, _z;
^
LedCube:17: error: from this location
LedCube.ino: In member function 'void LedCube::displayFrame(...)':
LedCube:20: error: 'frame' was not declared in this scope
LedCube:21: error: '_lPins' was not declared in this scope
In file included from LedCube.ino:2:0:
LedCube.h: At global scope:
LedCube.h:12: error: invalid use of non-static data member 'LedCube::_y'
int _x, _y, _z;
^
LedCube:27: error: from this location
In file included from LedCube.ino:2:0:
LedCube.h:12: error: invalid use of non-static data member 'LedCube::_x'
int _x, _y, _z;
^
LedCube:27: error: from this location
In file included from LedCube.ino:2:0:
LedCube.h:12: error: invalid use of non-static data member 'LedCube::_z'
int _x, _y, _z;
^
LedCube:27: error: from this location
LedCube.ino: In member function 'void LedCube::displayLayer(...)':
LedCube:31: error: 'frame' was not declared in this scope
LedCube:31: error: 'i' was not declared in this scope
LedCube:32: error: '_cPins' was not declared in this scope
LedCube:35: error: '_cPins' was not declared in this scope
invalid use of non-static data member 'LedCube::_y'

This report would have more information with
"Show verbose output during compilation"
enabled in File > Preferences.

Я просто хочу настроить таргетинг на эту ошибку, а не на остальных.

Лучший ответ:

class LedCube {
  private:
  int _x, _y, _z;
  byte _lPins[_y];
  byte _cPins[_z][_x];

Вышеприведенный код не имеет никакого смысла, Arduino или нет. (Помните, что Arduino использует С++).

Вы пытаетесь определить массивы _lPins и _cPins, у которых есть длины _x, _y, _z, которые неинициализированы. Класс должен иметь фиксированный размер, поэтому при его создании компилятор знает, сколько памяти выделяет его (перед вызовом конструктора). Как он может выделять память для неизвестных массивов?


(Отредактировано для добавления)

Я думаю, что StackOverflow имеет конструктивную политику ответов. Пожалуйста, дайте решение, если вы думаете, что я сделал что-то неправильно (именно поэтому я здесь).

Мне интересно узнать, почему вы принимаете ответ, в котором говорится: “Ваш код:… это неправильно”. но обижаться на меня. В принятом ответе нет кода решения, только некоторые рекомендации.

Этот ваш код, а не определение класса, также допускает ту же ошибку:

int _x, _y, _z;
//bool frame[y][z][x] = {0};
byte _lPins[_y];
byte _cPins[_z][_x];

Это также создает ошибку. Вы не можете объявить такой статический массив с ограничениями x, _y, _z, где x, _y, _z не являются константами. Массив не изменит свою длину в будущем при изменении x, _y, _z.


В вашем конструкторе вы передаете в качестве аргумента имя _x, которое также является переменной класса.

LedCube::LedCube(int x, int y, int z, byte lPins[], byte cPins[][_x]) {

С++ не позволяет назначать массивы следующим образом:

 _lPins = lPins;
 _cPins = cPins;

У вас много ошибок, а не только один, например.

LedCube:20: error: 'frame' was not declared in this scope
LedCube:21: error: '_lPins' was not declared in this scope

Вам действительно нужно пройти и очистить их все.


Аналогично, IIRC, новые и удаленные также не представлены на вашей платформе

Фактически Arduino предоставляет new и delete, а также malloc и free.


Я пытаюсь быть конструктивным, но нет однострочного исправления. Требуется переделка, извините, что рассказываю вам. И вы можете захотеть сделать некоторые учебники на С++. Код, который вы пишете (хотя я вижу, что вы пытаетесь сделать), вы надеетесь, что язык работает определенным образом, когда он просто не делает.


Возможная реализация

Ниже приведен возможный способ выделения структур пинов в конструкторе на основе заданных размеров массива. Я не думаю, что это отличная реализация, но, по крайней мере, она работает. Функция showPins показывает, что данные были сохранены правильно.

class LedCube {
  private:
    const int x_, y_, z_;
    byte * lPins_;
    byte * cPins_;
  public:
    LedCube(const int x, const int y, const int z, byte *lPins, byte *cPins);  // constructor

    void showPins () const;
};

byte lPins [3] = { 5, 6, 7 };
byte cPins [2] [4] = {
    { 1, 2, 3, 4 },    // 0
    { 8, 9, 10, 11 },  // 1
};

LedCube::LedCube (const int x, const int y, const int z, byte *lPins, byte *cPins)
    : x_ (x), y_ (y), z_ (z)
  {
  lPins_ = new byte [y];
  cPins_ = new byte [x * z];
  if (lPins_ == NULL || cPins_ == NULL)
    exit (1);
  memcpy (lPins_, lPins, sizeof (byte) * y);
  memcpy (cPins_, cPins, sizeof (byte) * x * z);
  }

void LedCube::showPins () const
  {
  Serial.println (F("lPins:"));
  for (int i = 0; i < y_; i++)
    Serial.println (lPins_ [i]);
  Serial.println (F("cPins:"));
  for (int j = 0; j < x_; j++)
    {
    Serial.print (F("z = "));
    Serial.println (j);
    for (int k = 0; k < z_; k++)
      Serial.println (cPins_ [j * z_ + k]);
    } 
  }

LedCube foo (2, 3, 4, (byte *) lPins, (byte *) cPins);

void setup() 
{
  Serial.begin (115200);
  Serial.println ();
  foo.showPins ();
}

void loop() 
{

}

Вывод:

lPins:
5
6
7
cPins:
z = 0
1
2
3
4
z = 1
8
9
10
11

Ответ №1

Ваш код: byte _lPins[_y]; byte _cPins[_z][_x]; неверен. С++ не поддерживает массивы переменной длины, что означает, что _y, _x, _z должны быть постоянными выражениями.

Помните, что размер объекта должен быть постоянным во время компиляции, и вы не будете делать эту ошибку еще раз.

“Правильным” способом решения этой проблемы является использование std::vector, но я считаю, что он не существует на вашей платформе, хотя вы должны проверить. IIRC, единственной доступной библиотекой является подмножество стандарта C, которое поступает из avr-libc.

Вам придется динамически распределять память по своему усмотрению. Аналогично, IIRC, new и delete также не предоставляются на вашей платформе (но опять же, вам придется проверить меня на этом), поэтому вам придется использовать malloc и free и делать что-то старый способ С. Есть много ресурсов, доступных о том, как сделать это в Интернете.

@Hamish

The reason i had it as Quiz::ui is because its not in the same cpp file its in a seperate file called util.cpp, this is for organisation reasons, if i do not do this it throws the error «Use of undeclared ‘ui'» so i assumed i needed to mention the class name similar to java

I often say «C++ is not Java», but mostly is in different context — memory management. Funnily, here it’s even more applicable. In Java you are supposed to put every (public) class in it’s own file (if I remember correctly), C++ doesn’t care, it also doesn’t care how you name your files . You can put the declaration in a header and then put the definitions in any cpp you want (as long as you don’t duplicate the class/method names). It also doesn’t care how many classes (exported or otherwise) you declare in a header file.

Well, if you make global Widgets variables, this can happen. As globals are created first. Before main is run.

Can i fix this?

You shouldn’t create anything that’s QObject derived before the QCoreApplication constructor has run. The first QObject you create should be the application object. My advice, forget global variables, especially since you appear to not have much experience with C++. In Java they are mostly okay, but with C++ they are a real pain and lead to all sorts of complications. Do as @mrjj suggested and put your objects as members of classes.

PS.

void appendInput(QString string) {
    Quiz::ui->input->setText(string);
}

These functions are global functions, and not class members, you should convert them to methods instead and in these methods you can operate your ui object.

Kind regards.

0 0 голоса
Рейтинг статьи
Подписаться
Уведомить о
guest

0 комментариев
Старые
Новые Популярные
Межтекстовые Отзывы
Посмотреть все комментарии

А вот еще интересные материалы:

  • Яшка сломя голову остановился исправьте ошибки
  • Ясность цели позволяет целеустремленно добиваться намеченного исправьте ошибки
  • Ясность цели позволяет целеустремленно добиваться намеченного где ошибка
  • Ошибка invalid stfs package horizon что делать
  • Ошибка invalid start mode archive offset что делать