Neden C ++ 'daki ok operatörü sadece *.


18

C ++ 'da, * operatörü bir yineleyici gibi aşırı yüklenebilir, ancak ok (->) (. *) Operatörü * operatörünü aşırı yükleyen sınıflarla çalışmaz. Önişlemcinin -> tüm örneklerini (* left) .right ile kolayca değiştirebileceğini ve yineleyicilerin uygulanmasını daha hoş hale getireceğini hayal ediyorum. -> farklı olmak için pratik bir neden var mı, yoksa bu sadece dilin / tasarımcıların tuhaflığı mı?

Yanıtlar:


16

Kural foo->bareşittir (*foo).barsadece yerleşik operatörler için geçerlidir.

Unary operator *her zaman işaretçi dereference semantiğine sahip değildir. Matris transpozisyonu, sıfır veya daha fazla ayrıştırıcı eşleşmesi veya hemen hemen her şey anlamına gelen bir kütüphane yapabilirim.

Eğer aşırı yüklenen herhangi bir şeyin operator *aniden operator ->istemediğiniz bir şeyi kazanması mantıklı olmayan anlambilim ile dili daha rahatsız edici hale getirecektir.

operator -> ayrı olarak yüklenebilir, bu yüzden isterseniz, minimum çaba ile bir tane aşırı yükleyebilirsiniz.

Ayrıca, böyle bir aşırı yükün operator ->, zincirdeki bir ham işaretçi döndürene kadar çağrıları otomatik olarak zincirleme gibi bazı oldukça ilginç özelliklere sahip olacağını unutmayın . Bu, akıllı işaretçiler ve diğer proxy türleri için oldukça kullanışlıdır.

#include <boost/make_shared.hpp>
#include <boost/shared_ptr.hpp>
#include <string>
#include <iostream>
#include <ostream>

struct Foo
{
    boost::shared_ptr<std::string> operator -> () const
    {
        return boost::make_shared<std::string>("trololo");
    }
};

int main()
{
    Foo foo;
    std::cerr << foo->size() << std::endl;
}

Örneğiniz neyi gösteriyor? Bir dizeye akıllı bir işaretçi döndürüyor ve bir şekilde boyut veriyor musunuz? Kafam karıştı.
Trevor Hickey

2
Cevabımın son paragrafını, ->operatör zincirlerinin bir şeye ham bir işaretçi elde edene kadar nasıl kullanıldığını, bir üyeye erişemediğini ve bir üyeye eriştiğini gösterir. Operatör -> zincirlemeseydi, paylaşılan_ptr ham bir işaretçi olmadığından örnek yanlış biçimlendirilir.
Lars Viklund

@LarsViklund: cevabınızın bir sorunu var: "operatör-> ... zincirdeki bir ham işaretçi dönene kadar operatör-> çağrılarını otomatik olarak zincirler" dediniz. Bu doğru değildir - A->Bsözdizimi zincirlerini en fazla 1 ek çağrı kullanarak. C ++ -> ikili sözdiziminin gerçekte yaptığı şey nesnenin opeartor->doğrudan çağrılması değildir - bunun yerine türüne bakar Ave ham bir işaretçi olup olmadığını kontrol eder. Daha sonra ->onu siler ve yürütürse B, aksi takdirde nesnenin çağrısını operator->yapar, sonucu siler (yerel ham işaretçiyi veya başka bir öğeyi kullanarak operator->ve daha sonra Bsonuç üzerinde çalışır
Guss

@Guss: Talebiniz için herhangi bir bölüm ve ayet bulamıyorum veya bir derleyicide çoğaltamıyorum. C ++ 11 13.5.6 / 1, uygun bir aşırı yüklenme varsa, x->molarak yorumlanması gerektiğini belirtir (x.operator->())->m. LHS operator->tekrar uygun aşırı yüke sahip bir şeyse, bu işlem sadece (*x).m5.2.5 / 2'nin olağan etkisi olana kadar tekrar eder .
Lars Viklund

8

"C ++ Programlama Dili", bu operatörlerin farklı olmaları için farklı olduklarını açıklar, fakat aynı zamanda şunları söyler:

Daha bu operatörlerin olandan sağlarsanız, o sağlamak için akıllıca olduğu gibi, eşdeğerlik sağlamak için akıllıca olabilir ++xve x+=1aynı etkiye sahip x=x+1basit bir değişken için xbazı sınıfın eğer ++, + =, = ve + sağlanır.

Yani çünkü dil tasarımcıları ayrı aşırı yük noktaları sağlanan görünüyor olabilir tercih ederim varsayarak daha farklı şekilde aşırı istediğiniz zaman onları aynı olmak istiyorum.


7

Genel bir kural olarak, C ++ esnekliği destekleyecek şekilde tasarlanmıştır, bu nedenle aşırı yükler *ve ->ayrıdır. Bunu yapmak oldukça sıra dışı olsa da, yeterince kötü yapmak istiyorsanız, bu aşırı yüklemeleri tamamen farklı şeyler yapmak için yazabilirsiniz (örneğin, C ++ içinde uygulanan etki alanına özgü bir dil için mantıklı olabilir).

Bununla birlikte, yineleyiciler her iki kullanımı da destekler. Eski uygulamalarda, (*iter).whateverbunun yerine gerektiren bir kütüphane bulabilirsiniz iter->whatever, ancak öyleyse, bu, dilin bir özelliği değil, uygulamada bir hatadır. Tüm standart kapların / algoritmaların / yineleyicilerin uygulanmasında yer alan iş miktarı göz önüne alındığında, bazı erken sürümlerin biraz eksik olması şaşırtıcı değildir, ancak asla bu şekilde olmaları amaçlanmamıştır.


Standart kütüphane kaplarının uygulandığını -> ya da yüklenebilir olduğunu fark etmedim.
Jakob Weisblat

3
C ++ 03 24.1 / 1 (*i).m, geçerli olan her yineleyicinin i->maynı anlam ile desteklenmesini gerektirir .
Lars Viklund
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.