“#Define me (* this)” tanımlamak iyi bir fikir mi?


19

Bu makro bazı genel üstbilgilerde veya daha iyisi bir derleyici komut satırı parametresi olarak tanımlanabilir:

#define me (*this)

Ve bazı kullanım örnekleri:

some_header.h:

inline void Update()
{
    /* ... */
}

main.cpp:

#include "some_header.h"

class A {
public:
    void SetX(int x)
    {
        me.x = x;   
        me.Update(); 
    }

    void SomeOtherFunction()
    {
        ::Update();
    }

    /*
        100 or more lines
        ... 
    */

    void Update()
    {
        // ... 
    }

    int x;  
};

Bir sınıf üyesine eriştiğimde bir sınıf yönteminde her zaman kullanıyorum meve her zaman kullandığım bir genel tanımlayıcıya erişiyorum ::. Bu, kodu tanımayan okuyucuya (muhtemelen birkaç ay sonra kendim) başka bir yere bakmaya gerek kalmadan erişilenlere ilişkin yerelleştirilmiş bilgiler verir. Ben tanımlamak istiyorum meçünkü this->her yerde çok gürültülü ve çirkin kullanarak bulmak . Ancak #define me (*this)iyi bir C ++ uygulaması olarak düşünülebilir mi? meMakro ile ilgili bazı pratik sorunlu noktalar var mı? Ve eğer C ++ programcısı olarak memakro kullanarak bazı kodların okuyucu olacak , ister misiniz ister misiniz?

Düzenleme: Çünkü birçok kişi meaçıkça kullanarak tam tersi değil , ama genellikle açık tam aksine. Bence "bu her yerde açık" ne faydaları net olmayabilir.

"Bunu her yerde açıkça" yapmanın faydaları nelerdir?

  • Kodun bir okuyucusu olarak neye erişildiğine dair kesinliğe sahipsiniz ve eriştiğinizi düşündüğünüze gerçekten erişilen, bazı uzak kodlarda doğrulamadan farklı şeylere konsantre olabilirsiniz.
  • Arama işlevini daha spesifik olarak kullanabilirsiniz. " this->x" Araması , size yalnızca " x" aramasından daha fazla aranan sonuçlar verebilir
  • Bir üyeyi sildiğinizde veya yeniden adlandırdığınızda, derleyici bu üyenin kullanıldığı yerlerde size güvenilir bir şekilde bildirim gönderir. (Bazı global işlevler aynı ada sahip olabilir ve açık bir şekilde kullanmıyorsanız hata sunabilirsiniz.
  • Kodu yeniden düzenlerken ve üyeden üye olmayan bir işlev yaptığınızda (daha iyi kapsülleme yapmak için) açık bir şekilde bu, düzenlemeniz gereken yeri gösterir ve bunu üye olmayan işlev parametresi olarak verilen sınıf örneğine kolayca işaretçiyle değiştirebilirsiniz.
  • Genellikle kodu değiştirirken, bunu açıkça kullanmadığınızda, bunu her yerde açıkça kullandığınızdan daha fazla olasılık vardır.
  • Açıkça dışarıdan üye ( object.membervs object.m_member) atarken açık "m_" den daha az gürültülü (bu noktayı tespit etmek için @Kaz sayesinde)
  • Bu açıkça tüm üyeler - öznitelikler ve yöntemler için evrensel olarak sorunu çözerken, “m_” veya diğer önek pratik olarak yalnızca öznitelikler için kullanılabilir.

Bu listeyi cilalamak ve genişletmek, diğer avantajları biliyor musunuz ve bunu her yerde açıklamak için vakalar kullanmak istiyorsanız bana bildirin .


3
Aynı ada sahip işlev bağımsız değişkenlerine ve üyelere sahip olmaktan ve açık "bu" öğeden kaçınmaktan kaçınmalısınız.
pjc50

4
Patronumun VB kodunu hatırlatıyor. Her yerde. Bencil gibi geliyor. : p Her neyse, şimdiye kadar verilen cevaplar her şeyi söylüyor.
MetalMikester

19
Harika bir fikir! Python geçmişinden gelenler için neden olmasın #define self (*this)? Hatta her iki makroyu karıştırabilir ve VB ve diğer Python'u taklit eden bazı dosyalara sahip olabilirsiniz. :)
logc

11
Neden sadece tüm çıkmak, yapması ve yapmaması: #include "vb.h", #Include pascal.hya #include FOTRAN.hve kodunuz gönderebilirsiniz dokunmak sonraki kişi var TDWTF .
Dan Neely

4
Lütfen, sadece hayır. Özellikleri olarak bildirerek kendinize biraz sorun yaşayabilirsiniz me_x.
Robot Gort

Yanıtlar:


90

Hayır öyle değil.

Daha yeşil meralara gittikten uzun yıl sonra kodunuzu koruyacak programcıya dikkat edin ve kullandığınız dilin ortak kurallarına uyun. C ++ 'da neredeyse hiç yazmak zorunda kalmazsınız this, çünkü sınıf sembol çözünürlük sırasına dahil edilir ve sınıf kapsamında bir sembol this->bulunduğunda ima edilir. Yani herkesin yaptığı gibi yazmayın.

Sık sık hangi sembollerin sınıf kapsamından geldiğini karıştırırsanız, olağan yaklaşım üyeler için ortak adlandırma modeli kullanmaktır (alanlar ve bazen özel yöntemler; genel yöntemler için kullanıldığını görmedim). Ortak olanlar ile son eklemeli içerir _veya önek m_veya m.


12
"C ++ 'da, bunu neredeyse hiç yazmak zorunda kalmazsınız" , bu tamamen alakasız bir konudur. Bazı insanlar (benim gibi) this, değişkenin yönteme göre yerel olmadığını açıkça belirtmek için yazmayı tercih eder . Buradaki soru, makronun mevar olup olmayacağıdır this, kullanılması gereken bir şey olup olmadığı değil .
Mehrdad

8
@Mehrdad: Çünkü OP açıkça me.yerine kullandığını söylüyor this->. Gerek olmadığı için this->gerek yoktur me.ve bu nedenle makro gerek.
Martin York

11
@LokiAstari: Bu sorudaki hiçbir şey OP'ye uzaktan bile this->"gerekli olup olmadığını " merak etmiyor . Aslında OP, this->gerekli olmamasına rağmen kullandığını söylüyor . Soru, bu cevabın aslında cevap vermediği yerineme. kullanılıp kullanılmayacağıdır . this->
Mehrdad

4
@Mehrdad: Ama sadece evet veya hayır demek çok sıkıcı bir cevap veriyor. Bu nedenle, cevaba nasıl ulaşıldığını açıklamada genellikle açıklamalar oldukça yararlıdır ( Nasıl cevap verilir ). Sonuç kullanmak değildir, çünkü OP'nin kullanımla ilgili yanlış bir tutumu vardır thisve bu nedenle tam dengeli bir sonuç elde etmek için bu konuda bir tartışma yapılması gerekir.
Martin York

1
+1 yalnızca neden "Hayır, bu kötü bir uygulama" demek yerine açıklamak için.
user253751

42

Böylece, yeni bir dil oluşturmak istiyorsunuz. Sonra bunu yapın ve C ++ sakatlamayın.

Bunu yapmamak için birkaç neden var:

  1. Her normal kodlama standardı makrolardan kaçınmayı önerecektir ( işte nedeni budur )
  2. Bu tür makrolarla kodu korumak daha zordur. C ++ 'da programlama yapan herkesin ne thisolduğunu bilir ve böyle bir makro ekleyerek aslında yeni bir anahtar kelime eklersiniz. Ya herkes sevdiği bir şeyi tanıtırsa? Kod nasıl olurdu?
  3. Bazı özel durumlar dışında kullanmamalısınız (*this).veya hiç kullanmamalısınız this->( bu cevaba bakın ve "this->" için arama yapın)

Kodunuz, #define R returngerçek kodda gördüğüm koddan farklı değil . Nedeni? Daha az yazarak!


Konudan biraz uzaklaşıyorum, ama burada 3. noktaya genişleyeceğim (kullanmayın (*this).veya this->bir sınıfta).

Her şeyden önce, (*this).ya this->da nesnenin üye değişkenlerine ya da işlevlerine erişmek için kullanılır. Kullanmak anlamsızdır ve daha fazla yazım anlamına gelir. Ayrıca, daha fazla metin olduğu için bu kodu okumak daha zordur. Bu, daha zor bakım anlamına gelir.

Peki, kullanmanız gereken durumlar this->nelerdir?

(a) Argümanın adının talihsiz seçimi.

Bu örnekte, this->bağımsız değişken üye değişkeniyle aynı ada sahip olduğundan gereklidir:

struct A {
  int v;
  void foo( int v ) {
    this->v =v;
  }
};

(b) şablonlar ve miras ile uğraşırken (bkz bu )

Bu örnek derlenemeyecektir, çünkü derleyici hangi isme verişmek için adlandırılmış olduğunu bilmiyor .

template< typename T >
struct A {
  A(const T& vValue):v(vValue){}

  T v;
};

template< typename T >
struct B : A<T>
{
    B(const T& vValue):A<T>(vValue){}

    void foo( const T & newV ) {
      v = newV;
    }
};

1
"Yani, yeni bir dil oluşturmak istiyorsun. Sonra yap ve c ++ sakatlamayın." - Katılmıyorum. C ve C ++ 'ın en büyük gücü esneklikleri. OP, C ++ 'ı sakatlamıyor, sadece kodlamasını kolaylaştırmak için esnekliğini belirli bir şekilde kullanıyor.
user253751

2
@immibis Doğru. Onun için daha kolay olan, herkes için daha zordur. Bir takımda çalıştığınızda, bu saçmalıkları koda sokmak sizi çok iyi yapmaz.
BЈовић

2
Cevabınız "tanımlar kötüdür" den farklı değildir.
Bay Lister

7
@MrLister Cevabım "aptal tanımlar kötülüktür". Söz konusu makronun kullanımı aptalca ve gösterdiğim gibi, hiç gerekli değil. Kod olmadan iyi ve daha iyi *this.vethis->
BЈовић

1
@Mehrdad İnsanlar hala üye değişkenlere önek ve son ek ekliyor mu? Temiz Kod gibi kitaplarla "düzeltildi" diye düşündüm . c ++ 11 öncesi this->kadar yararlıdır auto. Başka bir deyişle, kod gürültüsünü artırır.
BЈовић

26

Bunu yapmamanızı öneririm. Bu, bunu gördüğünde makronuza aşina olmayan bir okuyucuya büyük bir " WTF " kazandırır. Genel kabul görmüş olanların üzerinde gerçek bir ihtiyaç olmaksızın "yeni sözleşmeler" icat edildiğinde kod daha okunabilir hale gelmez.

bunu kullanmak her yerde çok gürültülü ve çirkin

Belki size anahtar kelime me(Visual Basic, sanırım?) Kullanarak bir çok programlama yaptığınız için böyle görünebilir . Ama aslında bu sadece alışkın olma meselesi - this->oldukça kısa ve deneyimli C ++ programcılarının çoğunun sizin görüşünüze katılmayacağını düşünüyorum. Ve yukarıdaki durumda ne kullanımında this->veya kullanımına meuygun - Eğer üye fonksiyonların içinde veri üyeleri erişirken dışarı bu anahtar kelimeleri bırakarak dağınıklığı az miktarda olsun.

Özel üye değişkenlerinizin yerel değişkenlerden ayırt edilmesini istiyorsanız, m_önek olarak bir şey bağlantısı veya onlara bir sonek olarak alt çizgi ekleyin (ancak burada da görebileceğiniz gibi , bu sözleşme bile birçok kişi için "çok gürültülü").


12
_sonek eklenmelidir ; önek olarak standart kitaplıkların ve satıcı uzantılarının dahili sembolleri için ayrılmıştır.
Jan Hudec

4
@ JanHudec Yalnızca __(iki alt çizgi) veya alt çizgi ile başlıyorsa büyük harfle başlıyorsa . Genel ad alanında olmadığı sürece, tek bir alt çizgi ve ardından küçük bir harf uygundur.
Eric Finn

1
@EricFinn: İki kuralı bir araya getirdim. İki alt çizgi veya alt çizgi, büyük harf iç semboller ve tek alt çizgi, küçük harf ise sisteme özel uzantılar içindir. Uygulamalar da kullanılmamalıdır.
Jan Hudec

@JanHudec Sisteme özgü uzantılar için kuralın farkında değildi. Yine de, yorumunuz için bir bağlam sağlamak için önceki yorumumu bırakacağım.
Eric Finn

2
@JanHudec: Küçük harf sisteme özel uzantılar için mi? C ++ standardının bunu gösteren kısmına bir referans gönderebilir misiniz?
Mehrdad

18

Lütfen yapma! Yazarak kaydetmek için her yerde makrolar nerede büyük bir kod tabanı ile baş etmeye çalışıyorum. Bunu bana yeniden tanımlamanın kötü yanı, ön işlemcinin, kapsamda olmadığı / uygulanmadığı durumlarda bile her yerde onun yerini alacağıdır, örneğin tek başına bir işlev, çalışma arkadaşınızın başka bir yerde bana çağrılan yerel bir değişkeni olabilir. hata ayıklamaktan mutlu olmayacak ... Sonunda tüm kapsamlarda kullanamayacağınız makrolar var.


6

HAYIR!

# Eğer birileri o başlığı içeriyorsa, hilenizi bilmeden ortaya çıkacak karışıklığı hayal edin ve dosyalarının başka bir yerinde "ben" adı verilen bir değişken veya işlev varsa. Yazdırılamaz hata mesajı ne olursa olsun korkunç bir şekilde karışırlardı.


Pratikte, IDE'leri ile fareyi "bana" götürmeleri ve tanımı görmeleri muhtemeldir.
user253751

2
@immibis: Pratikte, yine de "bu saçmalığı kim yazdı?" : P
cHao

@immibis: Çalıştığım en iyi kodlayıcıların çoğu fareyi kullanmıyor - çok yavaş.
JBRWilkinson

Gerçekten: bunu bir başlıkta itmek asıl sorun. Eğer cpp dosyanızda kullanırsanız hiç bir sorun görmüyorum. Pragma itme standart olarak olsaydı, bunu bir başlıkta nasıl yapacağınızı tavsiye ederdim, ama yapmayız. Benden sonra tekrar et. #defines geneldir.
Joshua
Sitemizi kullandığınızda şunları okuyup anladığınızı kabul etmiş olursunuz: Çerez Politikası ve Gizlilik Politikası.
Licensed under cc by-sa 3.0 with attribution required.