C ++ ile kodlanırken neden işaretçiler önerilmez?


45

C ++ kullanırken işaretçiler kullanmamanın tavsiye edildiğini bir yerden okudum. C ++ kullanırken işaretçiler neden bu kadar kötü bir fikir. İşaretçileri kullanmak için kullanılan C programcıları için, C ++ 'da daha iyi alternatif ve yaklaşım nedir?


40
lütfen "bir yere" bağla. Bağlam çok alakalı olabilir.

1
Bu soru sizin için umarım yararlıdır.
Garet Claborn,

Bu cevapların çoğu, birincil sebep olarak bellek sızıntısından kaçınmayı ifade eder. Son zamanlarda, uygulamalarımızdan birinin işaretçiler kullanmamıza rağmen bellek sızıntısı sorunu olduğunu hatırlayamıyorum. Bellek sızıntısı sorunlarınız varsa doğru araçları kullanmıyorsunuz veya ne yaptığınızı bilmiyorsunuz. Çoğu geliştirme ortamı, yerleşik sızıntıları otomatik olarak kontrol etmenin bir yoluna sahiptir. Bence bellek sızıntısı sorunlarının çöp toplanan dillerde izlemesinin çok daha zor olduğunu düşünüyorum, çünkü bunların oluşumları çok daha ince ve suçluyu bulmak için sık sık üçüncü taraf bir araca ihtiyacınız var. .
Dunk

1
@Dunk 'un yorumuna ek olarak, bazen yüksek seviyeli dillerde yerleşik çöp toplayıcıları doğru çalışmaz. Örneğin ActionScript 3'ün çöp toplayıcısı yok. Şu anda içinde, NetConnectionsunucudan bağlantısı kesilen örneklerle ( stackoverflow.com/questions/14780456/… ) ilgili bir hata var ve bir programda, özellikle de toplamayı reddedeceği birden fazla nesne olmasıyla ilgili bir sorun var. ...
Panzercrisis

... ( adobe.com/devnet/actionscript/learning/as3-fundamentals/… - aratın GCRoots are never garbage collected.ve paragrafı başlatınThe MMgc is considered a conservative collector for mark/sweep. ). Teknik olarak, bu AS3'te değil, Adobe Virtual Machine 2'de bir problemdir, ancak temelde yerleşik olarak çöp toplama işlemi olan daha yüksek seviyeli dillerde bunun gibi bir sorun yaşarsanız, genellikle hata ayıklama dili içinde gerçek bir yolunuz olmaz. Bu konular tamamen programın dışında. ...
Panzercrisis

Yanıtlar:


58

Bence normal işaretçiler yerine akıllı işaretçiler kullanmalısınız.

Bilgisayar bilimlerinde akıllı bir işaretçi, otomatik çöp toplama veya sınır denetimi gibi ek özellikler sağlarken bir işaretçiyi simüle eden soyut bir veri türüdür. Bu ek özellikler, verimliliği korurken işaretçilerin yanlış kullanımından kaynaklanan hataları azaltma amaçlıdır. Akıllı işaretçiler genellikle bellek yönetimi amacıyla işaret ettikleri nesneleri takip eder.

İşaretçilerin yanlış kullanımı büyük bir hata kaynağıdır: İşaretçiler kullanılarak yazılmış bir program tarafından yapılması gereken sürekli tahsis, yerinden çıkarma ve referanslama, bellek sızıntılarının oluşma riskini beraberinde getirir. Akıllı işaretçiler, kaynak ayırma işlemini otomatik hale getirerek bellek sızıntılarını önlemeye çalışır: işaretçi (veya bir dizi işaretleyicideki son işaretçi) bir nesneye son verildiğinde, örneğin kapsam dışına çıktığından, sivri uçlu nesne de imha edilir.

C ++ 'da vurgu, çöp toplama ve bellek sızıntısını önleme olacaktır (sadece iki isme). İşaretçiler dilin temel bir parçasıdır, bu yüzden onları kullanmamak, programları en iyi şekilde değerlendirmek dışında neredeyse imkansızdır.


22
tipik olarak klasik anlamda kesinlikle katı olmayan çöp toplama, daha fazla referans sayma. En azından smart ptr'de alışkınım ([boost | std] :: shared_ptr)
Doug T.

3
Bu cevap, sorunun yalnızca küçük bir yönü olan akıllı işaretçi ile sınırlıdır. Ek olarak, akıllı işaretçi çöp toplama değildir.
deadalnix

3
Ayrıca genel olarak RAII.
Klaim

3
Hayır, kastedilen bu değil. Sadece bir yönü var ve en önemlisi değil.
Konrad Rudolph

Akıllı işaretçilerin en önemli unsur olduğunu düşünüyorum, ancak daha birçokları olduğu konusunda hemfikirim.
DeadMG

97

“F * cking pointer kullanmayın” polemiğini yayınlayan kişi olduğum için burada yorum yapmam gerektiğini düşünüyorum.

Her şeyden önce, bir polemik olarak, açıkça aşırı bir bakış açısını temsil eder. Orada olan (ham) işaretçiler meşru kullanımları kesinlikle. Ancak ben (ve birçok profesyonel C ++ programcısı) bu vakaların oldukça nadir olduğunu düşünüyorum. Fakat gerçekte demek istediğimiz şudur:

İlk:

Ham işaretçiler hiçbir koşulda kendi hafızasına sahip olmamalıdır.

Burada “kendi hafızası” esas olarak bir noktada deleteo göstergede (ancak ondan daha genel) denildiği anlamına gelir . Bu ifade güvenli bir şekilde mutlak olarak alınabilir. Bunun tek istisnası, kendi akıllı işaretçinizi (veya başka bir bellek yönetimi stratejisini) uygulamanızdır. Ve orada bile normalde hala düşük seviyede akıllı bir işaretçi kullanmalısınız.

Bunun mantığı oldukça basittir: kendi belleğine sahip ham işaretçiler bir hata kaynağı ortaya çıkarır. Ve bu hatalar var olan yazılımda üretkendir: bellek sızıntıları ve çift silme - her ikisi de net olmayan kaynak sahipliğinin doğrudan bir sonucu (ancak tersi yönde).

Bu sorun, neredeyse hiç bir ücret ödemeden, sadece ham işaretçiler yerine akıllı işaretçiler kullanılarak tamamen ortadan kaldırılabilir (uyarma: bu yine de düşünmeyi gerektirir, elbette; paylaşılan işaretçiler döngülere neden olabilir ve böylece bir kez daha bellek sızıntılarına neden olabilir) - ancak bu kolayca önlenebilir).

İkinci:

İşaretçilerin C ++ 'da çoğu kullanımı gereksizdir.

Diğer dillerden farklı olarak, C ++ değer semantiği için çok güçlü bir desteğe sahiptir ve işaretçilerin indirilmesine gerek yoktur. Bu hemen gerçekleşmedi - tarihsel olarak, C ++, C'de kolay nesne yönelimini kolaylaştırmak için icat edildi ve kuvvetli bir şekilde işaretçiler tarafından bağlanmış nesne grafiklerinin oluşturulmasına dayandı. Fakat modern C ++ 'da bu paradigma nadiren en iyi seçimdir ve modern C ++ deyimleri çoğu zaman göstergelere ihtiyaç duymaz . İşaretçiler yerine değerler üzerinde çalışırlar .

Ne yazık ki, bu ileti C ++ kullanıcı topluluğunun büyük bölümlerinde hala anlaşılmamıştır. Sonuç olarak, yazılan C ++ kodlarının çoğu, kodu karmaşık, yavaş ve hatalı / güvenilmez kılan gereksiz işaretçilerle doludur.

Modern C ++ 'ı bilen birileri için, nadiren herhangi bir işaretleyiciye ihtiyaç duyacağınız açıktır (akıllı ya da ham; bunları yineleyici olarak kullanmak dışında). Sonuçta ortaya çıkan kod daha kısa, daha az karmaşık, daha okunaklı, genellikle daha verimli ve daha güvenilirdir.


5
Sigh ... bu gerçekten ikinci puan için ... 30'dan fazla oy alabilen cevap olmalı. Modern C ++ ' da işaretçiler nadiren gereklidir .
Charles Salvia

1
Peki ya örneğin Gui nesnesinin bir sürü doktor nesnesi var. Bunların her ikisi de işaretçilere sahiptir, böylece sınıf ileriye yönelik olarak ilan edilebilir (yeniden derlemelerden kaçınır) ve böylece nesne bir miktar boş durumda oluşturulduktan sonra yığında yaratılmak yerine (yeni ile) oluşturulduğunda başlatılabilir ve daha sonra dosyalanabilir mi? Bu, işaretçilerin tamamen geçerli bir kullanımı gibi görünüyor - kapsüllenmiş nesnelerin tümü öbek üzerinde olmamalı mı?
Martin Beckett

4
@Martin GUI nesneleri, işaretçi nesne grafiklerinin gerçekten en iyi çözüm olduğu bir durumdur. Ancak hatıra ham işaretçilerine karşı bir ferdi hala duruyor. Ya ortak işaretçiler kullanın ya da uygun bir mülkiyet modeli geliştirin ve ham işaretçiler aracılığıyla kontroller arasında yalnızca zayıf (= sahip olmama) ilişkileri var.
Konrad Rudolph

1
@ VF1 std::unique_ptr. Ayrıca, neden olmasın ptr_vec? Fakat genellikle bir değer vektörü hala daha hızlı bir şekilde değişebilir (özellikle hareket anlamında).
Konrad Rudolph

1
@gaazkam Kimse seni sadece standart konteynerler kullanmaya zorlamadı. Örneğin Boost, tamamlanmamış tipleri destekleyen bir harita uygulamasına sahiptir. Başka bir çözüm, tip silme kullanmaktır; boost::varianta recursive_wrapperile muhtemelen bir DAG'yi temsil etmek için en sevdiğim çözüm.
Konrad Rudolph

15

Bunun nedeni, ham belleğe erişim ve tahsislerinizden sonra temizleme gibi işaretçileri kullanmanın daha ılımlı yönlerini gizleyen soyutlamalar olduğundan. Akıllı işaretçiler, konteyner sınıfları ve RAII gibi tasarım desenleriyle, ham işaretçiler kullanma ihtiyacı azalır. Bu, herhangi bir soyutlama gibi, onların ötesine geçmeden önce gerçekte nasıl çalıştıklarını anlamanız gerektiğini söyledi.


11

Nispeten basit, C zihniyeti "Bir sorun mu var? Bir işaretçi kullan" dır. Bunu C dizelerinde, işlev işaretçilerinde, işaretçiler gibi işaretçilerde, işaretçi işaretçi için işaretçi, boşluk işaretçisi içinde, C ++ öğelerinin ilk günlerinde bile üye işaretçilerinde görebilirsiniz.

Ancak C ++ 'da bu görevlerin birçoğu veya tamamı için değerleri kullanabilirsiniz. Bir fonksiyon soyutlamasına mı ihtiyacınız var? std::function. Bu bir fonksiyon olan bir değer. std::string? Bu bir değer, bu bir dize. Tüm C ++ 'ta benzer yaklaşımlar görebilirsiniz. Bu, kodun hem insanlar hem de derleyiciler için analizini oldukça kolaylaştırır.


C ++ 'da: Bir sorun mu var? Bir işaretçi kullanın. Şimdi 2 probleminiz var ...
Daniel Zazula

10

Sebeplerden biri, çok geniş imleç uygulamasıdır. Kaplar üzerinde yineleme yapmak, fonksiyona geçerken büyük nesnelerin kopyalanmasından kaçınmak, önemsiz olmayan yaşam boyu yönetim, hafızada rastgele yerlere erişim, vb. İçin kullanılabilirler. hemen bilerek bağımsız olarak.

Kesin amaç için bir araç seçimi, kodu daha basit ve daha kasıtlı hale getirir - yinelemeler için yineleyiciler, yaşam boyu yönetimi için akıllı işaretçiler vb.


3

Yukarıda sıralanan nedenlerin yanı sıra, bariz bir tane var: daha iyi optimizasyonlar. Aliasing analizi, bir işaretçi aritmetik vesilesiyle çok karmaşıktır; bununla birlikte, referanslar bir optimize ediciyi ima eder, bu nedenle sadece referanslar kullanılırsa daha derin bir aliasing analizi mümkündür.


2

Jmquigley pointer ve pointer aritmetiği tarafından belirtilen bellek sızıntıları riskinin yanı sıra, işaretçilerin bellekteki her yeri "hata bulmak" ve "güvenlik açıkları" ile sonuçlanabileceği için sorunlu olduğu düşünülebilir .

Bu yüzden neredeyse C # ve Java ile terk edildiler.


C # 'da "terkedilmemiş" olmalarını bekle. Bu cevap kötü, korkunç bir yazım ve korkunç yanlış bir ifadeye sahip.
Ramhound

1
Neredeyse terk edildiler . Yerel bir konuşmacı olmadığım için özür dilerim.
k3b

1
Hey, heceleme konusunda yardımcı olabiliriz. Bekle demek ya da hariç demek mi istediniz?
GeliştiriciDon

1
C # 'da neredeyse terkedilmiş halde, imleci hala unsafeanahtar kelime belirterek etkinleştirebilirsiniz
saat

-1

C ++ , C , özelliklerin yanı sıra Nesneler ve Sınıfların çoğunu destekler . C zaten işaretçiler ve başka şeyler vardı.

İşaretçiler, Nesne Yönlendirme ile birleştirilebilen çok kullanışlı bir tekniktir ve C ++ bunları desteklemektedir. Ancak, bu teknik, öğretilmesi zor ve anlaşılması zor ve istenmeyen hatalara neden olması çok kolaydır.

Pek çok yeni programlama dili, işaretçileri Java, .NET, Delphi, Vala, PHP, Scala gibi nesnelerle kullanmıyor gibi görünmektedir. Ancak, işaretçiler hala “perde arkasında” kullanılmaktadır. Bu "gizli işaretçi" teknikleri "referanslar" olarak adlandırılır.

Her neyse, imleci (ler) i bir Programlama Örüntüsü, belirli problemleri çözmenin geçerli bir yolu ve Nesneye Yönelik Programlama olarak görüyorum .

Diğer geliştiricilerin farklı fikirleri olabilir. Ancak, öğrencilere ve programcılara aşağıdakileri öğrenmelerini öneririm:

(1) Nesnesiz işaretçiler kullanın

(2) işaretçisi olmayan nesneler

(3) nesnelere açık işaretçiler

(4) nesnelere "gizli" işaretçiler (AKA referansı ) ;-)

Bu sırayla.

Öğretmesi ve öğrenmesi zor olsa bile. Bu amaçlar için Nesne Pascal (Delphi, FreePascal, diğerleri) ve C++(Java veya C # değil) kullanılabilir.

Ve daha sonra, acemi programcılar, Java, C #, Nesneye Yönelik PHP ve diğerleri gibi programlama dillerini "nesnelere gizli işaretçiler" e taşıyabilirler.


19
C ++ olarak başladığı "Sınıflı C" den çok daha fazlası.
David Thornley

Neden C ++ ve C'yi hava fiyatına alıyorsunuz? Ve "gizli", "referanslar" ve her şey? Sen bir "satıcı" mısın ve "programlamaya" katılmıyor musun?
phresnel

Onları kalın harflerle yazmalıyım. Tırnaklar, hem de tam tersini vurgulamak için kullanılabilir
umlcat

-6

VC6 hakkında konuşmak, bir değişkenin (örneğin DWORD) bir sınıftaki bir işaretçiyi (örneğin başlattığınız) attığınızda, bu işaretçi yerel olsa bile, aynı yığını kullanan tüm işlevlerden sınıfa erişebilirsiniz. Örneklenen sınıf yerel olarak tanımlanır, ancak aslında değildir. Bildiğim kadarıyla, bir yığın değişkeninin, yapısının veya sınıfının herhangi bir adresi, barındırma sınıfının yaşamı boyunca benzersizdir.

Örnek:

class MyClass1 {
    public:
        void A (void);
        void B (void);
        void C (void);
    private:
        DWORD dwclass;
};

class MyClass2 {
    public:
        int C (int i);
};

void MyClass1::A (void) {
    MyClass2 *myclass= new MyClass2;
    dwclass=(DWORD)myclass;
}

void MyClass1::B (void) {
    MyClass2 *myclass= (MyClass2 *)dwclass;
    int i = myclass->C(0); // or int i=((MyClass2 *)dwclass)->C(0);
}

void MyClass1::B (void) {
    MyClass2 *myclass= (MyClass2 *)dwclass;
    delete myclass;
}

EDIT Orijinal kodun çok küçük bir kısmı. CSRecodset sınıfı yalnızca tüm gerçek kodun olduğu bir CXdbRecordset döküm sınıfıdır. Bunu yaparak, haklarımı kaybetmeden kullanıcının yazdıklarımdan faydalanmasına izin verebilirim. Veritabanı motorumun profesyonel olduğunu göstermiş gibi davranmıyorum ama gerçekten çalışıyor.

//-------------------------------------
class CSRecordSet : public CSObject
//-------------------------------------
{
public:
    CSRecordSet();
    virtual ~CSRecordSet();
    // Constructor
    bool Create(CSDataBase* pDataBase,CSQueryDef* pQueryDef);
    //Open, find, close
    int OpenRst(bool bReadBlanks=0,bool bCheckLastSql=0,bool bForceLoad=0,bool bMessage=1);     // for a given SQL
    int FindRecord(bool bNext);         // for a given SQL
    // TABLE must be ordered by the same fields that will be seek
    bool SeekRecord(int nFieldIndex, char *key, int length=0);  // CRT bsearch
    bool SeekRecord(int nFieldIndex, long key);     
    bool SeekRecord(int nFieldIndex, double key, int decimals);     
    bool SeekRecord(XSEK *SEK);     
    bool DeleteRecord(void);
    bool Close(void);
    // Record Position:
    bool IsEOF(void);           // pointer out of bound
    bool IsLAST(void);          // TRUE if last record
    bool IsBOF(void);           // pointer out of bound
    bool IsOpen(void);
    bool Move(long lRows);      // returns FALSE if out of bound
    void MoveNextNotEof(void);  // eof is tested
    void MoveNext(void);        // eof is not tested
    void MovePrev(void);        // bof is tested
    void MoveLast(void);
    void MoveFirst(void);
    void SetAbsolutePosition(long lRows);
    long GetAbsolutePosition(void);
    void GoToLast(void); // Restore position after a Filter
    // Table info
    long GetRecordCount(void);
    int GetRstTableNumber(void);
    int GetRecordLength(void); //includes stamp (sizeof char)
    int GetTableType(void);
    // Field info
    int GetFieldCount(void);
    void GetFieldName(int nFieldIndex, char *pbuffer);
    int GetFieldIndex(const char *sFieldName);
    int GetFieldSize(int nFieldIndex);
    int GetFieldDGSize(int nFieldIndex); // String size (i.e. dg_Boolean)
    long GetRecordID(void);
    int GetStandardFieldCount(void);
    bool IsMemoFileTable(void);
    bool IsNumberField(int nFieldIndex);
    int GetFieldType(int nFieldIndex);
    // Read Field value
    bool GetFieldValue(int nFieldIndex, XdbVar& var);
    bool GetFieldValueIntoBuffer(int nFieldIndex,char *pbuffer);
    char *GetMemoField(int nMemoFieldIndex, char *pbuffer, int buf_size);
    bool GetBinaryField(unsigned char *buffer,long *buf_size);
    // Write Field value
    void Edit(void); // required
    bool SetFieldValue(int nFieldIndex, XdbVar& var);
    bool SetFieldValueFromBuffer(int nFieldIndex,const char *pbuffer);
    bool Update(void); // required
    // pointer to the same lpSql
    LPXSQL GetSQL(void);
};

//---------------------------------------------------
CSRecordSet::CSRecordSet(){
//---------------------------------------------------
    pClass |= (CS_bAttach);
}
CSRecordSet::~CSRecordSet(){
    if(pObject) delete (CXdbRecordset*)pObject;
}
bool CSRecordSet::Create(CSDataBase* pDataBase,CSQueryDef* pQueryDef){
    CXdbQueryDef *qr=(CXdbQueryDef*)pQueryDef->GetObject();
    CXdbTables *db=(CXdbTables*)pDataBase->GetObject();
    CXdbRecordset *rst = new CXdbRecordset(db,qr);
    if(rst==NULL) return 0;
    pObject = (unsigned long) rst;
    return 1;
}
bool CSRecordSet::Close(void){
    return ((CXdbRecordset*)pObject)->Close();
}
int CSRecordSet::OpenRst(bool bReadBlanks,bool bCheckLastSql,bool bForceLoad, bool bMessage){
    unsigned long dw=0L;
    if(bReadBlanks) dw|=SQL_bReadBlanks;
    if(bCheckLastSql) dw|=SQL_bCheckLastSql;
    if(bMessage) dw|=SQL_bRstMessage;
    if(bForceLoad) dw|=SQL_bForceLoad;

    return ((CXdbRecordset*)pObject)->OpenEx(dw);
}
int CSRecordSet::FindRecord(bool bNext){
    return ((CXdbRecordset*)pObject)->FindRecordEx(bNext);
}
bool CSRecordSet::DeleteRecord(void){
    return ((CXdbRecordset*)pObject)->DeleteEx();
}
bool CSRecordSet::IsEOF(void){
    return ((CXdbRecordset*)pObject)->IsEOF();
}
bool CSRecordSet::IsLAST(void){
    return ((CXdbRecordset*)pObject)->IsLAST();
}
bool CSRecordSet::IsBOF(void){
    return ((CXdbRecordset*)pObject)->IsBOF();
}
bool CSRecordSet::IsOpen(void){
    return ((CXdbRecordset*)pObject)->IsOpen();
}
bool CSRecordSet::Move(long lRows){
    return ((CXdbRecordset*)pObject)->MoveEx(lRows);
}
void CSRecordSet::MoveNextNotEof(void){
    ((CXdbRecordset*)pObject)->MoveNextNotEof();
}
void CSRecordSet::MoveNext(void){
    ((CXdbRecordset*)pObject)->MoveNext();
}
void CSRecordSet::MovePrev(void){
    ((CXdbRecordset*)pObject)->MovePrev();
}
void CSRecordSet::MoveLast(void){
    ((CXdbRecordset*)pObject)->MoveLast();
}
void CSRecordSet::MoveFirst(void){
    ((CXdbRecordset*)pObject)->MoveFirst();
}
void CSRecordSet::SetAbsolutePosition(long lRows){
    ((CXdbRecordset*)pObject)->SetAbsolutePosition(lRows);
}
long CSRecordSet::GetAbsolutePosition(void){
    return ((CXdbRecordset*)pObject)->m_AbsolutePosition;
}
long CSRecordSet::GetRecordCount(void){
    return ((CXdbRecordset*)pObject)->GetRecordCount();
}
int CSRecordSet::GetFieldCount(void){
    return ((CXdbRecordset*)pObject)->GetFieldCount();
}
int CSRecordSet::GetRstTableNumber(void){
    return ((CXdbRecordset*)pObject)->GetRstTableNumber();
}
void CSRecordSet::GetFieldName(int nFieldIndex, char *pbuffer){
    ((CXdbRecordset*)pObject)->GetFieldName(nFieldIndex,pbuffer);
}
int CSRecordSet::GetFieldIndex(const char *sFieldName){
    return ((CXdbRecordset*)pObject)->GetFieldIndex(sFieldName);
}
bool CSRecordSet::IsMemoFileTable(void){
    return ((CXdbRecordset*)pObject)->IsMemoFileTable();
}
bool CSRecordSet::IsNumberField(int nFieldIndex){
    return ((CXdbRecordset*)pObject)->IsNumberField(nFieldIndex);
}
bool CSRecordSet::GetFieldValueIntoBuffer(int nFieldIndex,char *pbuffer){
    return ((CXdbRecordset*)pObject)->GetFieldValueIntoBuffer(nFieldIndex,pbuffer);
}
void CSRecordSet::Edit(void){
    ((CXdbRecordset*)pObject)->Edit();
}
bool CSRecordSet::Update(void){
    return ((CXdbRecordset*)pObject)->Update();
}
bool CSRecordSet::SetFieldValue(int nFieldIndex, XdbVar& var){
    return ((CXdbRecordset*)pObject)->SetFieldValue(nFieldIndex,var);
}
bool CSRecordSet::SetFieldValueFromBuffer(int nFieldIndex,const char *pbuffer){
    return ((CXdbRecordset*)pObject)->SetFieldValueFromBuffer(nFieldIndex,pbuffer);
}
bool CSRecordSet::GetFieldValue(int nFieldIndex, XdbVar& var){
    return ((CXdbRecordset*)pObject)->GetFieldValue(nFieldIndex,var);
}
bool CSRecordSet::SeekRecord(XSEK *SEK){
    return ((CXdbRecordset*)pObject)->TableSeek(SEK);
}
bool CSRecordSet::SeekRecord(int nFieldIndex,char *key, int length){
    return ((CXdbRecordset*)pObject)->TableSeek(nFieldIndex,key,length);
}
bool CSRecordSet::SeekRecord(int nFieldIndex,long i){
    return ((CXdbRecordset*)pObject)->TableSeek(nFieldIndex,i);
}
bool CSRecordSet::SeekRecord(int nFieldIndex, double d, int decimals)
{
    return ((CXdbRecordset*)pObject)->TableSeek(nFieldIndex,d,decimals);
}
int CSRecordSet::GetRecordLength(void){
    return ((CXdbRecordset*)pObject)->GetRecordLength();
}
char *CSRecordSet::GetMemoField(int nMemoFieldIndex,char *pbuffer, int BUFFER_SIZE){
    return ((CXdbRecordset*)pObject)->GetMemoField(nMemoFieldIndex,pbuffer,BUFFER_SIZE);
}
bool CSRecordSet::GetBinaryField(unsigned char *buffer,long *buf_size){
    return ((CXdbRecordset*)pObject)->GetBinaryField(buffer,buf_size);
}
LPXSQL CSRecordSet::GetSQL(void){
    return ((CXdbRecordset*)pObject)->GetSQL();
}
void CSRecordSet::GoToLast(void){
    ((CXdbRecordset*)pObject)->GoToLast();
}
long CSRecordSet::GetRecordID(void){
    return ((CXdbRecordset*)pObject)->GetRecordID();
}
int CSRecordSet::GetStandardFieldCount(void){
    return ((CXdbRecordset*)pObject)->GetStandardFieldCount();
}
int CSRecordSet::GetTableType(void){
    return ((CXdbRecordset*)pObject)->GetTableType();
}
int CSRecordSet::GetFieldType(int nFieldIndex){
    return ((CXdbRecordset*)pObject)->GetFieldType(nFieldIndex);
}
int CSRecordSet::GetFieldDGSize(int nFieldIndex){
    return ((CXdbRecordset*)pObject)->GetFieldDGSize(nFieldIndex);
}
int CSRecordSet::GetFieldSize(int nFieldIndex){
    return ((CXdbRecordset*)pObject)->GetFieldSize(nFieldIndex);
}

EDIT: DeadMG tarafından talep edildi:

void nimportequoidumomentquecaroule(void) {

    short i = -4;
    unsigned short j=(unsigned short)i;

}

1
Bu açıklama, açıkladığınız şeyi göstermek için bazı kodlarla önemli ölçüde geliştirilebilir. Asıl soru ile ilgili olduğunu hissediyorum, ancak bu senaryoda bizi bir tehlike konusunda uyarırsanız, sorunun konusunu daha iyi anlamanıza yardımcı olur.
GeliştiriciDon

1
Bu oyuncu DWORDküfürlü ve muhtemelen yanlıştır (DWORD bir işaretçiyi tutacak kadar geniş değildir). Yazılmamış bir işaretçiye ihtiyacınız varsa kullanın void*- ama C ++ 'da buna ihtiyaç duyduğunuzda, kodunuzda sık sık bir tasarım sorunu yaşarsınız.
Mat

Salvador, VC6 hakkında ve bunun olağandışı ve beklenmedik işaretçi kullanımına ilişkin bir şeyler söylemeye çalıştığınızı düşünüyorum. Örnek, yorumlardan yararlanabilir ve derleyiciden uyarılar görüyorsanız, soruyu yanıtlamanız konusunda bilgilendirici olabilir.
GeliştiriciDon

@Mat Bu örnek 32 bit işletim sistemi ve VC6 ++ derleyicisi içindir.
Salvador

6
Tamamen eski bir derleyicideki kötü koddan mı bahsediyorsunuz? Hayır teşekkürler.
DeadMG
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.