2010-09-09 22 views
19

İşte kodum -Türetilmiş * ile taban * arasındaki dönüşüm neden özel mirasla neden başarısız olur?

#include<iostream> 
using namespace std; 

class base 
{ 
public: 
    void sid() 
    { 
    } 
}; 

class derived : private base 
{ 
public: 
    void sid() 
    { 
    } 
}; 

int main() 
{ 
    base * ptr; 
    ptr = new derived; // error: 'base' is an inaccessible base of 'derived' 
    ptr->sid(); 
    return 0; 
} 

Bu derleme bir zaman hatası veriyor.

error: 'base' is an inaccessible base of 'derived' 

Derleyici sid() taban sınıfını denemeye çalışacak ve neden bu hatayı alıyorum? Birisi bunu açıklayabilir mi?

+0

"Sanal" yöntemini bildirmediniz. Tam olarak hangi hatayı alıyorsun? – Dirk

+8

Geçerli haliyle, bunun 'sid()' işleviyle ilgisi yoktur. Özel miras kullanıyorsunuz, bundan dolayı türetilmiş * 'den' tabana '' dönüşümü başarısız oluyor. Sorduğunuz şey bu mu, yoksa sid() yöntemi ile ilgili bir şey mi? – Naveen

+1

[Korunan türetilmiş sınıf] 'ın olası bir kopyası (http://stackoverflow.com/questions/433965/protected-derived-class) – kennytm

cevap

16

$ 11,2/4 eyalette

Burada

A base class B of N is accessible at R, if

  • an invented public member of B would be a public member of N, or
  • R occurs in a member or friend of class N, and an invented public member of B would be a private or protected member of N, or
  • R occurs in a member or friend of a class P derived from N, and an invented public member of B would be a private or protected member of P, or
  • there exists a class S such that B is a base class of S accessible at R and S is a base class of N accessible at R."

'B' 'Base' olduğu, 'n' 'Türetilmiş' ve 'R' ana olduğunu.

  1. 2. bulleti dikkate alınız - R, N veya ... sınıfının bir üyesi veya arkadaşında görülür. Bu madde 'R' (ana) 'nin üyesi veya arkadaşı değildir' N '(Türetilmiş)

  2. 3. mermi göz önünde bulundurun - R, bir sınıfta P üyesi veya üyesi ... . '. Bu Baba da Dolayısıyla biz 'Baz' bir erişilebilir sınıf olmadığı sonucuna varabiliriz kez daha bu fıkra

geçerli değildir

  • 4 Kurşun- düşünün yukarıdaki ile aynı nedenlerle geçerli değildir 'Türetilmiş'.

    $ 11,2/5 durumları - main erişildiğinde Base yana

    If a base class is accessible, one can implicitly convert a pointer to a derived class to a pointer to that base class (4.10, 4.11). [ Note: it follows that members and friends of a class X can implicitly convert an X* to a pointer to a private or protected immediate base class of X. —end note ]

    Derived erişilebilir bir sınıf değil, temel sınıf Türetilmiş sınıftan standart dönüşüm hasta biçimlidir. Bu yüzden hata.

    DÜZENLEME 2:

    Çalışma hatası bazı popüler derleyiciler mesajlar ve sizin daha iyi anlamak yardımcı olacaktır.'Erişilemez' kelimesinin tüm hata iletilerinde o kadar sık ​​ve tutarlı bir şekilde ortaya çıktığını unutmayın. Referanslar, N3000 taslak standardından alınmıştır. Ben Chusbad standardını kapsayan derinlemesine bir açıklama sağlanan son taslak :)

    GCC prog.cpp: In function ‘int main()’: prog.cpp:27: error: ‘base’ is an inaccessible base of ‘derived’

    Comeau Online "ComeauTest.c", line 26: error: conversion to inaccessible base class "base" is not allowed ptr = new derived;

    VS2010 error C2243: 'type cast' : conversion from 'derived *' to 'base *' exists, but is inaccessible

  • +0

    Referansınızı sağlayabilir misiniz? – Bruce

    +0

    @Bruce: Üzgünüm, referansların taslak standart N3000'den geldiğini söylemeyi unuttum. C++ 03'in bu konsepti anlamak için kafa karıştırıcı ifadeleri olduğunu gördüm. Benim yazımı buna göre güncelleyeceğim – Chubsdad

    +0

    Douglas Leeder'in ve ereOn'un insan tarafından okunabilir ve hızlı çözümler için cevaplarını görün. – mwjohnson

    35

    Sorunun miras özel olduğu gibi, bir baz işaretçisi türetilmiş bir işaretçi dönüştürmek olamaz şüpheli.

    +0

    Bunu neden yapamıyorum? Bunun uygulama sorunları neler? – Bruce

    +2

    Özel kalıtım, temel sınıf arabiriminin, alt sınıf kodundan başka bir kodla erişilebilir olmasını istemediğiniz anlamına gelir. – Klaim

    +7

    Chubsdad'ın cevabını yorumlamak için zaman harcamayı gerçekten düşünmemiştim ve bu benim bilmem gereken şeydi. Benim türetilmiş sınıf tanımımı üzerinde bir 'public' ifadesi eksik mi – User

    0

    sanal olarak taban sınıfta sid() fonksiyonunu ilan etmek gerekir. Sanal bir işlev, türetilmiş bir sınıf ile değiştirilebilir. Aksi takdirde, bir derleyici hatası alırsınız.

    +4

    Biliyorsunuz, insanlar reddederken nefret ediyorum ve yorum bırakmayın. –

    +0

    Bu cevabı aşağıya oylamadım, ama sanırım yanılıyor. Derleyiciler bir temel sınıf işlevi türetilmiş bir sınıf ile gizlemek için * uyarıları * verdiğini gördüm, ancak asla bir hata. –

    5

    bu deneyin:

    #include<iostream> 
    #include<conio.h> 
    using namespace std; 
    
    class base 
    { 
         private: 
         public: 
          virtual void sid() // You might want to declare sid virtual 
          { 
            cout<<"base"; 
          } 
          virtual ~base() // You then probably need a virtual destructor as well. 
          { 
          } 
    }; 
    
    class derived : public base //public inheritance 
    { 
         private: 
         public: 
          void sid() 
          { 
            cout<<"derived"; 
          } 
    }; 
    
    int main() 
    { 
        base * ptr; 
        ptr = new derived; 
        ptr->sid(); 
        getch(); 
        return 0; 
    } 
    
    +0

    Sanal sanal sid() 'yi mi kastediyorsunuz? Ayrıca 'sanal' olmak için temel sınıf yıkıcısına ihtiyacınız var. – Naveen

    +0

    @Naveen: Teşekkürler. Yıkıcıyı eklemek için yoldaydım;) Ayrıca, evet, "özel" bir yazım hatasıydı. – ereOn

    +0

    Sanal yıkıcı iyi bir fikir. Sanal işlevi sid işlevi üzerine koymak, özgün posterin belirtilen bir amacına aykırıdır. –

    6

    Sen class derivedclass base devralır ancak main() işlev bunu bilmiyor biliyoruz. main() işlev bunu bilmiyor nedeni class derivedclass base den ÖZEL miras yapılmış olmasıdır. Eğer new derivedptr atamak çalıştığınızda

    nedenle, işaretçi türleri uyumlu değildir.

    +0

    @WP: – Bruce

    +0

    Chubsdad'ın cevabını açıklayabilir misiniz? –

    8

    indirmek için henüz, ben erişilebilir bir açıklama çalışacağım.

    C++ 'da, 3 erişim düzeyi belirteci vardır: public, protected ve private. Bunlar WHO'nun yöntemleri, özniteliklere veya temel sınıflara erişebildiğini belirlemektir. Nesne Yönelimli diller arasında tipiktir.

    Burada, private devralmayı seçtiniz. Kavramsal olarak bu, Derived'un Base'dan miras almasına izin vermek anlamına gelir, bu genellikle bir uygulama ayrıntıları anlamına gelir. Sonuç olarak, "dış" bu ilişkinin farkında değildir. Bu, bu inaccessible iletisiyle derleyici tarafından zorlanır.

    Tasarım açısından bakıldığında, genellikle private devralmaya gerek yoktur. Ya Liskov İkame Prensibi uygulanır ve public devralma değerini kullanırsınız, ya bir uygulama detayıdır ve kompozisyonu kullanırsınız.

    0

    bu hata verir C2243: 'type cast': 'türetilmiş *' ile 'base *' arasında dönüştürme var, ancak erişilemeyen Bu türetilmiş sınıf özel olarak devralınmıştır. yaratılış gerçekleşir. türeyen nesneyi oluşturmak için ilk aramalar, gerçekleşmeyen temel sınıf nesnesini oluşturmaya gider. Soltuion, sınıfı genel olarak türetmektir. üye işlevleriyle sanal anahtar kelimenizi kullanıp kullanmadığınız fark etmez.