Cos'è ElectroYou | Login Iscriviti

ElectroYou - la comunità dei professionisti del mondo elettrico

C++: istanziare oggetto in constructor

Raccolta di codici sorgenti

Moderatore: Foto UtentePaolino

1
voti

[11] Re: C++: istanziare oggetto in constructor

Messaggioda Foto Utentefairyvilje » 20 ott 2022, 10:43

boiler ha scritto:Insomma, sto cercando di ottenere l'architettura a sinistra (che mi sembra pulita) e mi vedo quasi-costretto a realizzare quella a destra (che nel contesto delle classi in C++ mi sembra equivalete al "mettere tutto in variabili globali" in C).


Nessuna delle due architetture esiste. Non confondere il modo in cui includi i files con le dipendenze che definisci fra classi od altre entità.
Le dipendenze fra files sono gestite dal preprocessore, nemmeno dal C++. Il linguaggio in se non ha idea di cosa sia un file.

Fondamentalmente con le direttive #include stai solo dicendo come copiare ed incollare files insieme in un unico grosso da passare al compilatore. Quindi tutti i file finiscono per essere un'ammasso globale, che tu lo voglia o no; non funziona come in altri linguaggi quali js con moduli es o java.

Il modo corretto per approcciare il problema a livello di preprocessore è di inserire guards or #pragma once per ogni file header, in modo da evitare istanze ripetute nel processo di copy and paste. Per il resto includi quello che devi includere dove serve.

Lascia il problema delle dipendenze e la loro pulizia ai namespace, moduli (se usi c++ abbastanza recente) e gerarchia di classi :). In C++ è totalmente normale includere lo stesso file in più punti e non è considerato un problema in linea di principio se i suoi simboli sono usati.
"640K ought to be enough for anybody" Bill Gates (?) 1981
Qualcosa non ha funzionato...

Lo sapete che l'arroganza in informatica si misura in nanodijkstra? :D
Avatar utente
Foto Utentefairyvilje
14,9k 4 9 12
G.Master EY
G.Master EY
 
Messaggi: 3037
Iscritto il: 24 gen 2012, 19:23

0
voti

[12] Re: C++: istanziare oggetto in constructor

Messaggioda Foto UtenteGioArca67 » 20 ott 2022, 23:57

boiler ha scritto:Dopo aver istanziato la classe, chi vuole usarla deve chiamare il metodo init, che prende la configurazione e la applica a quello che la classe effettivamente fa. Se il flag che indica l'errore è attivo, init non attiva la classe.

Ma chi usa la classe non è lo stesso che chiama il metodo init?
Se sì qual è il problema dell' immutabilità? Se gli attributi sono privati e non ci sono setters come li modificano in corso d'opera?
Del resto chiamare un metodo senza aver chiamato prima init dà errore.
Non puoi allora inizializzare a null e non far funzionare la classe se prima non viene chiamata init?
Avatar utente
Foto UtenteGioArca67
3.945 4 6 9
Master
Master
 
Messaggi: 3930
Iscritto il: 12 mar 2021, 9:36

0
voti

[13] Re: C++: istanziare oggetto in constructor

Messaggioda Foto Utenteboiler » 23 ott 2022, 10:29

fairyvilje ha scritto:Nessuna delle due architetture esiste. Non confondere il modo in cui includi i files con le dipendenze che definisci fra classi od altre entità.

So di questa differenza, ma il limitare gli "includes" è un mezzo per obbligare il programmatore (o il manutentore in futuro) a rispettare l'architettura che si è stabilita.
Il fatto che il compiler mi dia un errore mi costringe a chiedermi cosa ho sbagliato.

Ovviamente potrei risolvere con un file global.h che include TUTTI i moduli e viene a sua volta incluso ovunque (sì, le guards ci sono). Ma è il primo passo verso lo spaghetti code.

Non facendolo si ha uno strumento per aumentare la qualità non-funzionale del codice: modularità, mantenibilità, testabilità...

Hai ragione che di queste proprietà al compiler non importa nulla, ma a me sì ;-)

Se torniamo all'esempio di cui sopra (main, foo, bar), immaginati che foo e bar siano un HAL, dove in bar c'è il codice specifico per il microcontroller, mentre foo è specifico per il PCB.
Specialmente in questo periodo, il poter cambiare una periferia (come per esempio un ADC) o tutto il microcontroller senza dover cambiare pezzi di codice ovunque, è un vantaggio. Se il codice che se ne occupa è ben incapsulato, riduco notevolmente lo sforzo per la modifica e per il testing.

È una filosofia che stiamo seguendo in modo abbastanza consistente in questo progetto, al punto che in realtà bar implementa il pimpl pattern per isolarsi completamente da foo.

GioArca67 ha scritto:Ma chi usa la classe non è lo stesso che chiama il metodo init?

No, se ci riferiamo allo schema in [9], init è in bar. L'"utente" è main e quello che non voglio è che main debba "conoscere" bar per poter usare foo.

Boiler
Avatar utente
Foto Utenteboiler
24,8k 5 9 13
G.Master EY
G.Master EY
 
Messaggi: 5263
Iscritto il: 9 nov 2011, 12:27

0
voti

[14] Re: C++: istanziare oggetto in constructor

Messaggioda Foto UtenteGioArca67 » 23 ott 2022, 11:18

Mi sembra quasi impossibile quello che vuoi fare.

Se vuoi un foo solo e la possibilità di avere bar diversi da poter usare in foo senza cambiare nulla devi implementare un meccanismo in cui bar fornisce a richiesta le caratteristiche per fare l'init che vengono raccolte da foo il quale le interpreta e costruisce l'init di volta in volta necessario.
Avatar utente
Foto UtenteGioArca67
3.945 4 6 9
Master
Master
 
Messaggi: 3930
Iscritto il: 12 mar 2021, 9:36

0
voti

[15] Re: C++: istanziare oggetto in constructor

Messaggioda Foto Utenteboiler » 23 ott 2022, 11:31

GioArca67 ha scritto:Mi sembra quasi impossibile quello che vuoi fare.

È fattibilissimo ed è una delle basi della programmazione orientata agli oggetti!
https://en.wikipedia.org/wiki/Information_hiding

Se vuoi un foo solo e la possibilità di avere bar diversi da poter usare in foo senza cambiare nulla

Credo che ci sia un malinteso. C'è una sola classe bar, che accetta una configurazione. Di questa classe possono esserci piú istanze.

Quello a cui mi riferivo era una modifica di bar in una differente versione del software, non coesistente con la prima, completamente compatibile verso l'alto con la vecchia (concetto di interfaccia, che in C++ non esiste, ma si può simulare con una classe astratta).

Boiler
Avatar utente
Foto Utenteboiler
24,8k 5 9 13
G.Master EY
G.Master EY
 
Messaggi: 5263
Iscritto il: 9 nov 2011, 12:27

0
voti

[16] Re: C++: istanziare oggetto in constructor

Messaggioda Foto Utentegvee » 23 ott 2022, 13:39

Puoi fare uno schema di classi un po' meglio elaborato di quello nel messaggio 8 ?

A me non è chiaro se ci deve essere una sola istanza di bar, che dovrà essere comune a tutte le altre classi (p.e. foo), oppure ogni classe foo dovrà avere una istanza diversa di bar. Mi sembra che l'approccio del puntatore è già stato preso in considerazione.

Se non ho capito male parliamo del primo caso, ma se non vuoi che sia visibile dal main, da qualche parte dovrai pure inizializzare bar.

O_/
Avatar utente
Foto Utentegvee
1.180 2 7
Stabilizzato
Stabilizzato
 
Messaggi: 415
Iscritto il: 11 feb 2018, 20:34

0
voti

[17] Re: C++: istanziare oggetto in constructor

Messaggioda Foto Utentefairyvilje » 23 ott 2022, 15:53

>>>Specialmente in questo periodo, il poter cambiare una periferia (come per esempio un ADC) o tutto il microcontroller senza dover cambiare pezzi di codice ovunque, è un vantaggio. Se il codice che se ne occupa è ben incapsulato, riduco notevolmente lo sforzo per la modifica e per il testing.

Il problema da te presentato all'inizio nulla assomiglia a quella che è una più realistica rappresentazione del business case espressa in #13. Senza contesto la qualità di una risposta è tendenzialmente terribile :mrgreen:.
Capirei si trattasse di IP o materiale legato a brevetti, ma aspetti architetturali di quel tipo sono talmente "normali" nel loro essere stato dell'arte che non capisco il senso di una reticenza così stretta.

Come pensavo, quel problema di dipendenze ed ordine di esecuzione dei costruttori si risolve... non avendolo. Perché è vero che si può risolvere forzando il linguaggio, ma un buon 80% delle volte significa che si sta facendo qualcosa di sbagliato a livello di design.

Considera questa architettura:
  • una gerarchia di classi per rappresentare le periferiche come risorse in modo astratto, colla loro specifica interfaccia, basate su una classe virtuale base Resource
  • un loro wrapper che integra anche l'interfaccia per l'implementazione (ImplResource : Resource).
  • una classe base virtuale MC che come interfaccia presenta una lista di Resource come capabilities.
  • una classe base virtuale Board che come interfaccia presenta una lista di Resource come requisiti.
  • classi derivate da MC che implementano i veri modelli di microcontrollore la lista di capabilities come oggetti ImplResource. Questi sono basati su classi derivate da ImplResource e dalla tipologia specifica di risorsa direttamente in loco nella classe basata su MC.
  • classi derivate da Board che rappresentano vere istanze con una resource list effettiva (ed eventuale logica interna se devi farne una simulazione, ma questo è out of scope).

In questo modo MC e Board e le rispettive classi derivate che rappresentano modelli di controllori e board reali non si devono parlare direttamente ed eviti ogni forma di interferenza anche a livello di dipendenze, visto che queste sono spostate su Resource tramite una relazione "has".

Codice che ovviamente non compila. È solo per chiarire la gerarchia discussa sopra.
Codice: Seleziona tutto
class Resource;
class ImplResource : virtual Resource;

class Serial: virtual Resource;
class I2C: virtual Resource

class MC{
   virtual const List<ImplResources>& capabilities() = 0;
}

class Board{
   virtual const List<Resources>& required() = 0;
}

class InstanceMC: MC{
   class LocalSerial: Serial, ImplResource;
   class LocalI2C: I2C, ImplResource;
}

class InstanceBoard: Board;


In realtà visto che stiamo parlando di applicazioni embedded, tutto questo andrebbe realizzato sfruttando il meno possibile funzioni virtuali in favore dei template e traits che sono risolti a tempo di compilazione. Ma questo è il meno.
"640K ought to be enough for anybody" Bill Gates (?) 1981
Qualcosa non ha funzionato...

Lo sapete che l'arroganza in informatica si misura in nanodijkstra? :D
Avatar utente
Foto Utentefairyvilje
14,9k 4 9 12
G.Master EY
G.Master EY
 
Messaggi: 3037
Iscritto il: 24 gen 2012, 19:23

Precedente

Torna a Firmware e programmazione

Chi c’è in linea

Visitano il forum: Nessuno e 10 ospiti