2016-08-01 12 views
0

Beispiel: Die Klasse (Bibliothek) verwendet ein Array der standardmäßigen festen Größe. Sagen wir 64 Bytes. Im Programm benötigen Sie jedoch eine größere Größe, beispielsweise 128 Byte. Was wäre der beste Ansatz, wenn Sie die Bibliothek nicht jedes Mal neu schreiben möchten?Definieren Array-Größe in Bibliothek, ohne es für jede neue Verwendung zu ändern?

Ich habe versucht, diese falschen Code, indem Sie demonstrieren (mit #ifndef#define):

// myClass.h ***************************************** 

#ifndef myClass_h 
#define myClass_h 

#ifndef EXAMLPE 
#define EXAMLPE 64 
#endif 

class myClass{ 
     ... 
    private: 
     byte myArray[EXAMLPE]; // Use EXAMLPE to allocate array 
} 

#endif 


// Program.ino *************************************** 

// Override the default value without modifying the library 
#define EXAMLPE 128 
#include "myClass.h" 
// this does not work because of different scope, says compiler 

EDIT: Ich möchte feste Größe Array machen, wie es einfach ist, und es wird als gute Praxis auf 2 kb RAM betrachtet Plattform

EDIT 2: Ich verstehe nicht die ganze Argumentation in den Kommentar und auch warum meine Frage nicht bewertet wird. Ich bin natürlich kein großartiger Programmierer, ich weiß nichts über Vektoren oder Vorlagen, und darum bitte ich um Hilfe.

Ich bin auf der Suche nach einer Methode, wie Sie feste Größe Array in der Bibliothek aus Hauptcode in der Kompilierzeit festlegen.

Und schließlich: Weiß jemand, warum ich EXAMPLE was not declared in this scope kompilieren erhalten Fehler, wenn ich #ifndef Beispiel löschen ... # endif Linien aus Header? Ist es nicht so, dass es unabhängig vom Umfang ist?

+0

Es gibt keine "Scope" wenn Includes beteiligt sind; Sie werden wörtlich zur Quelle hinzugefügt. –

+2

Verwenden Sie einen 'std :: vector'? – GManNickG

+1

oder Vorlage die Klasse mit der Größe. – Jarod42

Antwort

0

C++ unterstützt keine Laufzeitgrößen-Arrays. Wenn Sie also zur Kompilierungszeit nicht wissen, welche Speichergröße Sie benötigen, ist ein Array das falsche Werkzeug für den Job. Ich würde stattdessen vorschlagen, dass Ihr Objekt nur einen Zeiger enthält, und verwenden Sie dann neu, um den Datenblock basierend auf einem bestimmten Laufzeitwert dynamisch zuzuweisen.

Beachten Sie, dass der folgende Code nur zur Demonstration der oben genannten Idee dient und nicht getestet wurde und wahrscheinlich nicht kompiliert wird.

class myClass { 
private: 
    byte *myData; 
public: 
    myClass(std::size_t dataSize) : 
      myData(new byte[dataSize]) 
    {} 
    myClass(const myClass&) = delete; 
    myClass(myClass&&) = delete; 
    myClass& operator=(const myClass&) = delete; 
    myClass& operator=(myClass&&) = delete; 
    ~myClass() 
    { 
     delete[] myData; 
    } 
}; 

Wenn auf der anderen Seite, die Größe zum Zeitpunkt der Kompilierung bekannt ist, aber Sie nicht wollen, die Header-Datei jedes Mal, wenn Sie die Größe ändern bearbeiten müssen Sie stattdessen eine Template-Klasse verwenden könnten, erlauben diese Benutzer stellen Kompilierzeitparameter bereit, wenn sie die Klasse verwenden. Zum Beispiel:

template<size_t dataSize> 
class myClass { 
private: 
    byte myArray[dataSize]; 
}; 

Die Klasse kann dann mit einem benutzerdefinierten Format zum Zeitpunkt der Kompilierung bekannt wie folgt erstellt werden:

auto foo = myClass<128>(); 
+0

@Combinatix Dann haben Sie sich den zweiten Teil der Antwort zum Templating angesehen? – Vality

+0

@Combinatix Wenn Sie denken, dass Sie die Größe des Arrays ändern müssen, dann wissen Sie nicht, wie viele Sensoren es gibt. Wenn Sie das getan hätten, müssten Sie sich keine Gedanken über die Größe machen. Du tust etwas, das hier nicht ganz stimmt ... Geh zurück und besuche dein Design und deine Anforderungen und finde heraus, wo dein Fehler liegt. –

+0

@Combinatix Verwenden Sie ** nicht ** '' '' und 'lösche' wie in der vorgeschlagenen Lösung gezeigt. Es gibt keine Notwendigkeit, Speicher wie dieses in modernem C++ zu verwalten, und sehr wenig Grund, es in früheren Inkarnationen der Sprache zu tun. Es ist problematisch, anfällig für Lecks und nur eine schlechte Idee herum. Verwenden Sie stattdessen 'std :: array' oder' std :: vector'. –

4

Compile-Zeit

Wenn Ihre Größe bei der Kompilierung definiert ist Zeit, könnten Sie eine Vorlagenklasse mit der Größe als Vorlage Argument verwenden.

template<int EXAMPLE> 
class myClass{ 
     ... 
    private: 
     byte myArray[EXAMPLE]; 
}; 

oder Sie könnten den std::array Container verwenden.

vs. Laufzeit

jedoch feste Größe Arrays sind nicht sehr flexibel. Ich rate daher dringend, stattdessen vectors zu verwenden.Sie können nicht nur festlegen eine Standardgröße für Ihren Vektor, aber diese Größe angepasst werden kann, dynamisch, ohne dass Sie über die Speicherverwaltung zu kümmern, Kopierkonstruktoren, Zuweisungsoperator, etc ...

class myClass { 
    public: 
     myClass(int mysize=64) : myVector(mysize) {}  
    private: 
     std::vector<byte> myVector; // no size needed here 
}; 
+0

Anscheinend wird die Verwendung dynamischer Arrays auf Arduino nicht empfohlen, da es Probleme mit RAM-Fragmentierung, Stack-Überlauf usw. verursacht. – Combinatix

+0

@Combinatix Ich würde mich für eine Referenz zu diesen Problemen interessieren. Die allgemeinen Bemerkungen, die ich über die Vermeidung der dynamischen Speicherzuweisung auf Arduino gelesen habe, basierten meist auf den üblichen Fehlern bei der manuellen Zuweisung. Wenn Sie Vektoren wie oben beschrieben verwenden, sollten Sie sicher bleiben. Beachten Sie, dass das Risiko eines Stack-Überlaufs mit Ihrem festen Array größer ist, da lokale Objekte auf dem Stapel mit begrenzter Größe zugewiesen werden, während Sie bei Vektoren flexibel bleiben. Wenn Sie keine dynamische Zuweisung wünschen, wäre der Kompilierungszeit-Sizing der einzige Ausweg. – Christophe

0

Warum die Verwendung nicht ersetzen eines Arrays für einen Vektor und definieren Methoden, um die maximale Größe des Vektors zu manipulieren. So etwas wie:

#include <vector> 


myClass{ 

private: 
    vector<int> v; 
    int maxSize 
public: 
    myClass(int size){ 
     v.reSize(size); 
     maxSize = size; 

    } 
    void add(int byte){ 
     if(v.size()<maxSize){ 
      v.push_back 
     } 
    } 
} 
0

Die Arduino IDE einige Tricks macht, wenn die .ino-Dateien in einer einzigen CPP-Datei konvertieren

  • erstellen Funktionsprototypen
  • schließlich #include Nachbestellung
  • (?)

Dies könnte Ihre

#define EXAMLPE 128

Th verschieben Die Vorlage Lösung ist am besten für Arduino, denke ich. Vektoren und dynamische Mem-Nutzung ist sehr gefährlich mit nur 2kB RAM (auf einem UNO).