OOP vs Inline dengan Arduino

8

Saya telah pemrograman untuk beberapa waktu sekarang tetapi saya baru di Arduino dan Pemrograman AVR. Pertanyaan utama yang saya miliki tentang pemrograman pengendali-mikro ini adalah apakah ada perbedaan besar dalam merancang kode di Object Orientated Classes vs pemrograman inline yang lebih tradisional yang saya lihat dalam banyak contoh?

Dengan kata lain di dunia Arduino / AVR Controllers apakah ada penghematan dengan Memory dan Performance menggunakan kelas atau sebaliknya?

Katakanlah misalnya kita memiliki Kelas:

class SomeClass(){

private:
   int x;
   int y;

public:
   void foo();
   void bar();
}

SomeClass thisClass;
thisClass.foo();
thisClass.bar();

Apakah akan ada peningkatan kinerja atau memori merancang program dengan cara yang lebih inline seperti:

int x;
int y;

void foo(){ /*** Do something ***/};
void bar(){ /*** Do more stuff ***/};

Saya mencoba melakukan beberapa pencarian di Stack Exchange dan Google tetapi tidak dapat menemukan jawaban yang cukup saya cari hal terdekat yang dapat saya temukan adalah Pertanyaan Stack Exchange ini.

Alasan saya bertanya tentang ini adalah saya memiliki proyek yang perlu seringan mungkin dan saya tidak jelas bagaimana saya harus merancang program saya di lingkungan ini.


Edit

Terima kasih atas jawabannya, ini telah menjelaskan banyak hal. Ada satu hal yang tidak saya jelaskan.

Katakanlah Anda memiliki kelas yang Anda rancang yang menggunakan u8glib sebagai berikut:

class UserInterface{
private:
   U8GLIB_ST7920_128X64 Display;

public:
   UserInterface();
}

Bagaimana cara Anda menggunakan "Memori Dinamis" seperti:

UserInterface::UserInterface(){
   UserInterface::Display = U8GLIB_ST7920_128X64(LCD_E_PIN, LCD_RW_PIN, LCD_RS_PIN, U8G_PIN_NONE);
}
Andy Braham
sumber

Jawaban:

2

Pertanyaan utama yang saya miliki tentang pemrograman pengendali-mikro ini adalah apakah ada perbedaan besar dalam merancang kode di Object Orientated Classes vs pemrograman inline yang lebih tradisional yang saya lihat dalam banyak contoh?

...

Dengan kata lain di dunia Arduino / AVR Controllers apakah ada penghematan dengan Memory dan Performance menggunakan kelas atau sebaliknya?

Ya, ada perbedaan besar antara menggunakan C atau C ++ untuk sistem tertanam skala kecil seperti Arduino / AVR. C ++ memungkinkan lebih banyak informasi disediakan untuk optimisasi kompiler.

Jika Anda menerapkan kerangka kerja OOP, platform atau runtime C ++ dan kelas juga dapat membantu dengan arsitektur perangkat lunak dan penggunaan kembali. Di Cosa sejumlah pola desain OOP digunakan untuk mencapai antarmuka untuk kedua programmer aplikasi dan programmer driver perangkat. Yang paling umum adalah delegasi .

Menggunakan kelas abstrak, fungsi anggota virtual, sebaris, dan template dapat membantu mencapai cetak kaki yang lebih rendah dan kinerja yang lebih tinggi daripada implementasi tradisional. Sebagai contoh, kelas Cosa Pin adalah X5-X10 lebih cepat dari inti Arduino dan pada saat yang sama lebih kecil dalam cetak-kaki. Silakan lihat tolok ukurnya .

Satu hal yang harus "dihapuskan" dari pemrograman C ++ tradisional adalah penggunaan baru / hapus (malloc / gratis). Dengan ukuran SRAM hanya beberapa Kbyte menggunakan tumpukan sangat banyak risiko. Jawabannya adalah kelas statis dan data berbasis stack.

Ada banyak lagi yang bisa dikatakan tentang arsitektur kerangka OOP tapi saya harap ini membantu menjawab pertanyaan awal Anda.

Bersulang!

Mikael Patel
sumber
Jawaban bagus! Saya memperbarui pertanyaan saya bertanya tentang bagaimana menyiasati memori dinamis (baru / hapus / malloc / gratis). Apakah Anda memiliki input untuk tidak menggunakan alokasi memori dinamis? Haruskah semua yang perlu dibagikan di seluruh kelas bersifat global? Itu kedengarannya tidak benar bagi saya, saya selalu diajari untuk tidak menggunakan global jika Anda bisa membantu.
Andy Braham
Komentar singkat tentang contoh UserInterface Anda di atas. Tampilan sebenarnya komposisi objek (bukan referensi / pointer) sehingga Anda tidak perlu yang baru. Anda perlu memulai Tampilan. Konstruksi UserInterface akan terlihat seperti ini. UserInterface::UserInterface() : Display(LCD_E_PIN, LCD_RW_PIN, LCD_RS_PIN, U8G_PIN_NONE) { ... }. Parameter konstruktor Tampilan yang diperlukan harus diteruskan ke konstruktor UserInterface.
Mikael Patel
OOP adalah tentang enkapsulasi, menyembunyikan data, jadi berbagi harus minimum (nol). Tujuannya adalah agar kurang lebih hanya memiliki sejumlah objek statis global yang berinteraksi. Mereka memegang dan menyembunyikan negara global. Untuk objek, data anggota adalah keadaan lokal yang tidak dinamis. Untuk mencapai tujuan, Anda perlu lagi serangkaian trik; transformasi program.
Mikael Patel
Sebuah contoh; Pertimbangkan desain kelas BitSet yang mungkin memiliki jumlah anggota variabel. Solusi yang jelas adalah menghitung jumlah byte yang dibutuhkan dan menggunakan new / malloc. Alternatifnya adalah meneruskan penyimpanan sebagai parameter ke konstruktor BitSet. Alternatif ketiga adalah kelas templat dengan jumlah elemen sebagai parameter. Ini memungkinkan variabel anggota yang merupakan jumlah byte yang diperlukan. Silakan lihat Cosa / BitSet.hh untuk detail lebih lanjut tentang varian transformasi program ini. Ada lebih banyak transformasi.
Mikael Patel
Saya memperbarui contoh UserInterface saya, apakah itu pendekatan yang kurang lebih benar? Saya pikir saya sekarang memiliki pemahaman yang sangat baik tentang bagaimana menerapkan apa yang saya butuhkan.
Andy Braham
4

Alasan Anda tidak dapat menemukan jawabannya adalah karena jawabannya adalah Ya dan Tidak.

Untuk hal-hal kelas dasar - mendefinisikan kelas Anda dengan metode dll dan instantiating objek dari itu - ada sedikit perbedaan dalam hasil akhir dibandingkan dengan "vanilla" C. Optimalisasi kompiler sangat baik sekarang bahwa kinerjanya sama saja. Ya, mungkin ada sedikit peningkatan dalam penggunaan memori karena Anda melewati pointer tambahan dengan setiap pemanggilan metode (bukan yang foo(int x)Anda miliki foo(MyClass *this, int x)) tapi itu sangat kecil sehingga tidak terlihat.

Perbedaan besar datang ketika Anda mulai bermain dengan polimorfisme dan topik lanjutan lainnya. Ketika mulai melakukan program-program kompleks ini kompiler tidak selalu tidak dapat mengetahui fungsi mana yang diperlukan dan mana yang tidak, dan itu tidak dapat memotong fungsi yang tidak digunakan ( "pengumpulan sampah" ). Jadi Anda mungkin berakhir dengan kode yang lebih besar.

Itu tidak berarti kode lebih lambat, hanya potongan kode yang berkeliaran yang tidak pernah melakukan apa pun.

Yang lebih penting adalah mengelola memori dinamis Anda lebih baik daripada yang biasa Anda lakukan. Karena ada sejumlah kecil memori, tumpukan sangat kecil, dan akibatnya mudah terfragmentasi. Penciptaan dinamis dan penghancuran objek ( new myClass, delete myClassObject, dll) sangat buruk. Objek kelas benar-benar perlu didefinisikan secara statis (dalam lingkup global adalah yang paling umum) atau sementara dialokasikan pada stack (instance lokal). Kalau tidak, Anda meminta masalah - dan yang pertama Anda ketahui adalah hal-hal aneh terjadi (tidak ada laporan kesalahan atau pengecualian, Anda lihat ...).

Majenko
sumber
Baiklah jika saya memahami ini dengan benar di dunia pemrograman ini, kelas digunakan untuk lebih dari peran organisasi dan portabilitas daripada OOP sejati dan bahwa hal-hal harus dialokasikan secara statis dan eksplisit daripada dinamis. Terima kasih banyak, ini membuat banyak akal dan menjelaskan mengapa saya telah melihat contoh dan apa yang tidak ditulis sebagaimana adanya.
Andy Braham