Bir const üye işlevi neden bir statik veri üyesini değiştirebilir?


86

Aşağıdaki C++programda, bir statik veri üyesini bir constişlevden değiştirmek iyi çalışıyor:

class A 
{
  public:   
    static int a; // static data member

    void set() const
    {
        a = 10;
    }
};

Ancak statik olmayan bir veri üyesini bir constişlevden değiştirmek işe yaramaz:

class A 
{
  public:   
    int a; // non-static data member

    void set() const
    {
        a = 10;
    }
};

Bir constüye işlevi neden bir staticveri üyesini değiştirebilir ?


Bize hangi platform ve derleyiciyle çalıştığınızı söylerseniz yardımcı olur musunuz? Böylece davranışın sizin özel kurulumunuzla ilgili bir hata olup olmadığını veya davranışın gerçekten doğru olup olmadığını ve sadece açıklanması gerekip gerekmediğini belirleyebiliriz.
Alex Zywicki

Linux platformunda @AlexZywicki G ++ derleyicisi.
msc

8
Gerek yok. Bu bilinçlidir ve tüm C ++ derleyicileri bunu desteklemelidir. Ama neden böyle iyi sorular artık oylanmıyor?
Bathsheba

18
Bu bir dupe, ancak daha iyi bir MCVE sayesinde diğerinden daha iyi yazılmış, bu yüzden bunu hedef olarak kullandım.
Baum mit Augen

5
Buradaki motivasyon const, bir nesnenin üye işlevinin o nesneyi değiştiremeyeceği anlamına gelir . Aynı sınıftaki diğer nesneleri veya sınıfla staticilişkili verileri, sınıfın belirli bir örneğini değil, değiştirebilir. (Veya mutablebu kuralın istisnası olarak oluşturulmuş veri üyeleri.)
Davislor

Yanıtlar:


100

Kural bu, hepsi bu. Ve iyi bir sebepten dolayı.

constEğer olmayan değiştiremez bir üye işlev aracı üzerinde eleme mutableolmayan staticsınıf üyesi değişkenleri.

Biraz rasyonalizasyon sunarak, nitelikli üye işlevindeki thisişaretçi constbir consttürdür ve thisdoğası gereği bir sınıfın örneğiyle ilişkilidir . staticüyeler bir sınıf örneğiyle ilişkili değildir. Bir staticüyeyi değiştirmek için bir örneğe ihtiyacınız yoktur : kendi durumunuzda yazarak bunu yapabilirsiniz A::a = 10;.

Yani, ilk durumda, düşünmek a = 10;için kısaltma olarak A::a = 10;ve ikinci durumda, kestirme olarak düşünmek this->a = 10;tipi beri derlenebilir olmadığı, thisolduğu const A*.


1
Sadece burada hafif bir hatası: Yeniden atamak olamayacağına göre thisişaretçi, bu türdendir const A* const içinde constbireyin durumda.
Taylor Hansen

2
@TaylorHansen this, işaretçi türünün bir prvalue'dur. Sınıf dışı türlerin değerleri asla cv nitelikli değildir.

21

C ++ Standardına göre (9.2.3.2 Statik veri üyeleri)

1 Statik veri üyesi, bir sınıfın alt nesnelerinin parçası değildir ...

Ve (9.2.2.1 Bu işaretçi)

1 Statik olmayan (9.2.1) üye fonksiyonun gövdesinde, bu anahtar kelime, değeri fonksiyonun çağrıldığı nesnenin adresi olan bir prvalue ifadesidir. Bir X sınıfının üye işlevindeki bunun türü X * 'dir. Üye işlevi sabit olarak bildirilmişse, bunun türü const X * , ...

Ve sonunda (9.2.2 Statik olmayan üye fonksiyonları)

3 ... ad araması (3.4), id ifadesindeki adı bazı C sınıfının statik olmayan türden olmayan bir üyesine çözümlerse ve id ifadesi potansiyel olarak değerlendirilirse veya C X veya bir temel sınıfsa X'de, id ifadesi (* this) kullanılarak bir sınıf üyesi erişim ifadesine (5.2.5) dönüştürülür. solundaki sonek ifadesi olarak (9.2.2.1) . Şebeke.

Böylece bu sınıf tanımında

class A 
{
  public:   
    static int a; 

    void set() const
    {
        a = 10;
    }
};

statik veri üyesi a , sınıf türündeki bir nesnenin alt nesnesi thisdeğildir ve işaretçi , statik veri üyesine erişmek için kullanılmaz. Dolayısıyla herhangi bir üye fonksiyon, statik olmayan sabit veya sabit olmayan veya statik bir üye fonksiyon, sabit olmadığı için veri üyesini değiştirebilir.

Bu sınıf tanımında

class A 
{
  public:   
    int a; 

    void set() const
    {
        a = 10;
    }
};

statik olmayan veri üyesi a, sınıf türündeki bir nesnenin bir alt nesnesidir. Bir üye işlevinde ona erişmek için ya bu sözdiziminin bir üye erişim sözdizimi kullanılır. thisVeri üyesini değiştirmek için sabit bir işaretçi kullanamazsınız . Ve bu işaretçi aslında const A *işlevin içinde bir türe sahiptir, setçünkü işlev niteleyici ile bildirilmiştir const. Bu durumda işlevin niteleyicisi yoksa, veri üyesi değiştirilebilir.


13

Şey, bir sınıfın bir elemanı işlevi, eğer Aolan const, daha sonra türü thisolduğu const X*ve bu şekilde değiştirilmiş olan olmayan statik veri üyeleri engeller (örneğin, Cf, C ++ standart ):

9.3.2 Bu işaretçi [class.this]

Statik olmayan (9.3) üye işlevin gövdesinde, this anahtar sözcüğü, değeri işlevin çağrıldığı nesnenin adresi olan bir prvalue ifadesidir. Bir X sınıfının üye işlevindeki bunun türü X * 'dir. Üye işlevi const olarak bildirilmişse, bunun türü const X *, ...

Eğer abir statik olmayan veri üyesi, daha sonra a=10aynı this->a = 10türü dahi izin verilmez, hangi thisolduğu const A*ve ailan edilmemiş mutable. Böylece, varlığın void set() consttürünüthisconst A* bu erişime izin verilmez.

Eğer astatik veri üyesi, aksine, daha sonra a=10içermeyen thishiç; ve static int atek başına beyan edilmediği sürece const, ifadeye a=10izin verilir.


1

constBir üzerinde eleme üye işlevi değiştirmek olamaz yollarla non-mutable, non-static sınıf veri üyeleri .

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.