Re: Jak správně rozdělit C++ projekt
Miroslav Mraz
mrazik na volny.cz
Pondělí Srpen 23 21:12:46 CEST 2021
V C++ se spíš používá zapouzdření všeho co jde do tříd. Moderní
překladač umí kód dobře optimalizovat, takže výsledek je někdy i kratší
než čisté C. Na globální proměnné a nějaké makra můžete klidně
zapomenout. Struktura by byla asi nějak takto (c++14):
////////////////// hlavicky ////////////////////////
#ifndef AB_H
#define AB_H
// misto define se spis pouziva constexpr kvuli lepsi typove kontrole
constexpr int GLOBAL = 666;
constexpr int FACT (const int n) { // faktorial se vyhodnoti uz pri
prekladu
return n <= 1 ? n : n * FACT (n - 1);
}
// oddelit co je mozne a dat fo samostatnych trid
// jednotlive tridy dat do samostatnych souboru (.h, .cpp)
class A {
static constexpr int PIN = 5; // byvale define
int a,b; // byvale globalni promenne
public:
// lze volat konstruktory i pro int, ale budou nastaveny v setup()
explicit A () : a(1), b(2) {};
void setup () { // jednoduche funkce mohou byt definovany v .h, pak
jsou inline
a = FACT (PIN); // vyhodnoceno jako a = 120
b = GLOBAL; // ...
}
void loop (); // v .h muze byt jen deklarace, vlastni kod pak v .cpp
};
class B {
// tady muzou mit promenne stejna jmena jako v A, jsou to ale jina
pametova mista
static constexpr int PIN = 10;
int a,b;
protected: // puvodni globalni funkce tykajici se jen teto casti lze
deklarovat jako chranene metody
void function ();
public:
explicit B () {};
void setup () {
a = GLOBAL;
b = PIN;
}
void loop ();
};
#endif // AB_H
///////////////////// zapouzdreni /////////////////////////
#ifndef SUPER_H
#define SUPER_H
#include "ab.h"
class Super {
A a;
B b;
public:
explicit Super() : a(),b() {};
void setup () {
a.setup();
b.setup();
}
void loop () {
a.loop();
b.loop();
}
};
#endif // SUPER_H
///////////////////// main.cpp ///////////////////
#include "super.h"
static Super super;
void setup () {
super.setup();
}
void loop () {
super.loop();
}
/** Definice metod, ma byt v samostatnych souborech pro A, B **/
void A::loop () {
printf ("A::a=%d, b=%d\n", a, b);
a += 1; // ...
}
void B::loop () {
printf ("B::a=%d, b=%d\n", a, b);
function();
b -= 5;
}
void B::function () {
printf("call protected %s\n", __FUNCTION__);
b += 4;
}
Samozřejmě si to každý může udělat po svém, možností je dost a Arduino
není v používání zapouzdření důsledné, takže lze čekat problémy. Nicméně
chci tím říct, že přístup k řešení problému je v každém jazyce jiný a je
dobré si to předem rozmyslet a složitější strukturu programu přizpůsobit
paradigmatu jazyka už od začátku. Dodatečné úpravy pak bývají dost pracné.
Mrazík
Dne 23. 08. 21 v 16:48 Petr Labaj napsal(a):
> Asi jde o to, o co jde.
> Jestli to má být přehledné a pochopitelné pro Vás, nebo i pro nějaké
> cizí lidi, případně to má sloužit třeba pro zápočet na škole.
>
> Řekl bych, že je dobré mít pohromadě věci, které patří k sobě.
> Za sebe si myslím, že dobrým zvykem je, že "include" by neměl obsahovat
> výkonný kód, ale jenom makra a deklarace.
> A skládání výkonného kódu pak nechat na projektu/make/linkeru.
> Ale je-li to jen pro Vás, a vyhovuje Vám to, tak klidně skládat i *.c.
> Podle klíčových slov "setup" a "loop" to bude nějaká Arduinovina, takže
> to zřejmě nebude kdovíjak rozsáhlý projekt.
>
> Kdybych to dělal já, tak bych věci, které patří k sobě, dal do jednoho
> souboru. Případně i s globálními proměnnými, které k tomu patří.
> Do jednoho *.h, které bych pak do všech modulů includoval, bych pak dal
> deklarace všech funkcí ze všech modulů.
> A také deklarace proměnných (s příznakem "extern") , ale jen těch, které
> se používají ve více modulech.
> Takže globálky, použité jen jedním modulem, by zůstaly jen v něm.
> Což funguje jako aspoň triviální kontrola a přehled, co se používá různě
> křížově.
>
> Anebo třeba úplně jinak. ;-)
>
> PL
>
Další informace o konferenci Hw-list