Sanal / saf sanal açıklandı


347

Bir fonksiyonun sanal olarak tanımlanması ve saf sanal ile aynı olması tam olarak ne anlama gelir?

Yanıtlar:


340

Gönderen Wikipedia'nın Sanal fonksiyonu ...

Nesne yönelimli programlamada, C ++ ve Object Pascal gibi dillerde, sanal bir işlev veya sanal yöntem, dinamik dağıtmanın kolaylaştırıldığı devralınabilir ve geçersiz kılınabilen bir işlev veya yöntemdir. Bu kavram, nesne yönelimli programlamanın (OOP) (çalışma zamanı) polimorfizm bölümünün önemli bir parçasıdır. Kısacası, bir sanal işlev yürütülecek bir hedef işlevi tanımlar, ancak hedef derleme zamanında bilinmeyebilir.

Sanal olmayan bir işlevden farklı olarak, sanal bir işlev geçersiz kılındığında, en türetilmiş sürüm yalnızca oluşturulduğu düzeyden ziyade sınıf hiyerarşisinin tüm düzeylerinde kullanılır. Bu nedenle, temel sınıfın bir yöntemi sanal bir yöntemi çağırırsa , temel sınıfta tanımlanan sürüm yerine türetilmiş sınıfta tanımlanan sürüm kullanılır.

Bu, türetilmiş bir sınıfta hala geçersiz kılınabilen sanal olmayan işlevlerin tersidir, ancak "yeni" sürüm yalnızca türetilmiş sınıf ve aşağıda kullanılır, ancak temel sınıfın işlevselliğini hiç değiştirmez.

buna karşılık..

Saf sanal işlev veya saf sanal yöntem, türetilmiş sınıf soyut değilse türetilmiş bir sınıf tarafından uygulanması gereken sanal bir işlevdir.

Saf bir sanal yöntem mevcut olduğunda, sınıf "soyut" olur ve kendi başına başlatılamaz. Bunun yerine, saf sanal yöntemleri uygulayan türetilmiş bir sınıf kullanılmalıdır. Türetilmiş sınıfı bu yüzden saf sanal her taban sınıfı tanımlanmış olup gerekir tanımlamak veya bu türetilmiş bir sınıf, özet ve örneği alınamaz. Yalnızca soyut yöntemi olmayan bir sınıf somutlaştırılabilir.

Bir sanal, temel sınıfın işlevselliğini geçersiz kılmak için bir yol sağlar ve saf sanal bunu gerektirir .


10
Yani ... saf sanal bir anahtar kelime mi yoksa sadece kullanılan bir terim mi?
Justin

198
sanal boşluk İşlev () = 0; saf bir sanal. "= 0" saflığı belirtir.
Goz

8
Justin, 'saf sanal' yalnızca "bu işlev temel sınıf tarafından uygulanamaz." Bir sanal sözcüğün sonuna "= 0" eklenmesi anlamına gelen bir terimdir (anahtar kelime değil, aşağıdaki cevabıma bakın). işlevi "saf" yapar
Nick Haddad

14
Stroustrup'un bir pureanahtar kelime eklemek istediğini söylediğine inanıyorum , ancak Bell Labs, C ++ 'ın büyük bir sürümünü yayınlamak üzereydi ve yöneticisi bu geç aşamada buna izin vermeyecekti. Anahtar kelime eklemek çok önemli.
quark

14
Bu iyi bir cevap değil. Sadece sanal olanları değil, herhangi bir yöntemi geçersiz kılabilir. Daha fazla ayrıntı için cevabıma bakın.
Asik

212

Burada birkaç kişi tarafından tekrarlanan Wikipedia'nın sanal tanımına yorum yapmak istiyorum. [Bu cevap yazılırken] Wikipedia, sanal bir yöntemi alt sınıflarda geçersiz kılınabilecek bir yöntem olarak tanımladı. [Neyse ki, Wikipedia o zamandan beri düzenlenmiş ve şimdi bunu doğru bir şekilde açıklıyor.] Bu yanlış: sadece sanal olanları değil, herhangi bir yöntem alt sınıflarda geçersiz kılınabilir. Sanal olan size polimorfizm, yani çalışma zamanında bir yöntemin en türetilmiş geçersiz kılma seçimini yapma yeteneğidir .

Aşağıdaki kodu göz önünde bulundurun:

#include <iostream>
using namespace std;

class Base {
public:
    void NonVirtual() {
        cout << "Base NonVirtual called.\n";
    }
    virtual void Virtual() {
        cout << "Base Virtual called.\n";
    }
};
class Derived : public Base {
public:
    void NonVirtual() {
        cout << "Derived NonVirtual called.\n";
    }
    void Virtual() {
        cout << "Derived Virtual called.\n";
    }
};

int main() {
    Base* bBase = new Base();
    Base* bDerived = new Derived();

    bBase->NonVirtual();
    bBase->Virtual();
    bDerived->NonVirtual();
    bDerived->Virtual();
}

Bu programın çıktısı nedir?

Base NonVirtual called.
Base Virtual called.
Base NonVirtual called.
Derived Virtual called.

Türetilmiş her Base yöntemini geçersiz kılar: sadece sanal olanı değil, aynı zamanda sanal olmayanı da.

Bir Base-pointer-to-Türved (bDerived) olduğunda, NonVirtual çağrıldığında Base sınıfı uygulamasını çağırır. Bu derleme zamanında çözümlenir: derleyici, bDerived bir Base * olduğunu görür, NonVirtual sanal değildir, bu nedenle sınıf Base çözünürlüğü yapar.

Ancak, Virtual çağrıldığında Derived sınıf uygulaması çağrılır. Sanal anahtar sözcüğü nedeniyle, yöntemin seçimi derleme zamanında değil , çalışma zamanında gerçekleşir. Derleme zamanında burada olan şey, derleyicinin bunun bir Base * olduğunu görmesi ve sanal bir yöntem çağırmasıdır, bu nedenle sınıf Base yerine vtable'a bir çağrı ekler. Bu vtable, çalışma zamanında somutlaştırılır, dolayısıyla en türetilmiş geçersiz kılma için çalışma zamanı çözünürlüğü.

Umarım bu çok kafa karıştırıcı değildir. Kısacası, herhangi bir yöntem geçersiz kılınabilir, ancak sadece sanal yöntemler size polimorfizm, yani en türetilen geçersiz kılmanın çalışma zamanı seçimini verir. Bununla birlikte, uygulamada, sanal olmayan bir yöntemin geçersiz kılınması kötü uygulama olarak kabul edilir ve nadiren kullanılır, bu yüzden birçok kişi (Wikipedia makalesini yazanlar dahil) sadece sanal yöntemlerin geçersiz kılınabileceğini düşünmektedir.


6
Vikipedi makalesi (ki hiçbir şekilde savunmam mümkün değil) sanal bir yöntemi "alt sınıflarda geçersiz kılınabilecek bir yöntem" olarak tanımladığı için, aynı ada sahip diğer sanal olmayan yöntemlerin bildirilmesi olasılığını dışlamaz. Buna aşırı yükleme denir.

26
Tanım yine de yanlıştır. Türetilmiş bir sınıfta geçersiz kılınabilen bir yöntem tanım gereği sanal değildir; yöntemin geçersiz kılınıp kılınamayacağı "sanal" tanımıyla ilgisizdir. Ayrıca, "aşırı yükleme" genellikle aynı adda ve dönüş türünde, ancak aynı sınıfta farklı bağımsız değişkenlere sahip birden çok yönteme sahip olmak anlamına gelir; aynı imzayı, ancak türetilmiş bir sınıfta ima eden "geçersiz kılmadan" çok farklıdır. Polimorfik olmayan (sanal olmayan baz) yapıldığında, genellikle "gizleme" olarak adlandırılır.
Aşık

5
Bu kabul edilen cevap olmalı. Bu soruyla ilgili başka kimse yapmadığı için buraya bağlanmak için zaman ayıracağım özel Wikipedia makalesi tam bir çöp. +1, iyi efendim.
josaphatv

2
Şimdi bir anlam kazandı. Teşekkürler, efendim, herhangi bir yöntemin türetilmiş sınıflar tarafından geçersiz kılınabileceğini ve derleyicinin farklı durumlarda hangi işlevin çağrıldığını seçmek için nasıl davranacağını doğru bir şekilde açıkladığınız için teşekkür ederiz.
Doodad

3
Derived*Noktayı eve götürmek için aynı işlev çağrılarına sahip bir a eklemek yararlı olabilir . Aksi takdirde harika cevap
Jeff Jones

114

Sanal anahtar kelime C ++ 'a polimorfizmi destekleme yeteneği verir. Aşağıdaki gibi bir sınıfın nesnesine bir işaretçi olduğunda:

class Animal
{
  public:
    virtual int GetNumberOfLegs() = 0;
};

class Duck : public Animal
{
  public:
     int GetNumberOfLegs() { return 2; }
};

class Horse : public Animal
{
  public:
     int GetNumberOfLegs() { return 4; }
};

void SomeFunction(Animal * pAnimal)
{
  cout << pAnimal->GetNumberOfLegs();
}

Bu (aptal) örnekte, GetNumberOfLegs () işlevi, çağrıldığı nesnenin sınıfına göre uygun sayıyı döndürür.

Şimdi, 'SomeFunction' fonksiyonunu düşünün. Hayvandan türetildiği müddetçe, ona ne tür bir hayvan nesnesinin geçtiği umurunda değildir. Derleyici, temel sınıf olduğu için herhangi bir Hayvan türevi sınıfı bir Hayvana otomatik olarak atacaktır.

Bunu yaparsak:

Duck d;
SomeFunction(&d);

çıktı '2' olurdu. Bunu yaparsak:

Horse h;
SomeFunction(&h);

çıktı '4' olurdu. Bunu yapamayız:

Animal a;
SomeFunction(&a);

çünkü GetNumberOfLegs () sanal işlevi saf olduğu için derlenmeyecektir, yani sınıflar (alt sınıflar) türetilerek uygulanmalıdır.

Saf Sanal İşlevler çoğunlukla aşağıdakileri tanımlamak için kullanılır:

a) soyut sınıflar

Bunlar, onlardan türetmeniz ve daha sonra saf sanal işlevleri uygulamanız gereken temel sınıflardır.

b) arayüzler

Bunlar, tüm işlevlerin saf sanal olduğu ve böylece tüm işlevleri türetmeniz ve uygulamanız gereken 'boş' sınıflardır.


Örneğin, saf sanal yöntemin bir uygulamasını sağlamadığınız için # 4 yapamazsınız. Kesinlikle değil çünkü yöntem saf sanal.
iheanyi

@iheanyi Temel sınıftaki saf sanal yönteme uygulama sağlayamazsınız. Dolayısıyla # 4 numaralı durum hala hatalıdır.
prasad

32

C ++ sınıfında sanal , bir yöntemin bir alt sınıfın üzerine yazılabileceğini (yani uygulayabileceğini) belirten anahtar kelimedir. Örneğin:

class Shape 
{
  public:
    Shape();
    virtual ~Shape();

    std::string getName() // not overridable
    {
      return m_name;
    }

    void setName( const std::string& name ) // not overridable
    {
      m_name = name;
    }

  protected:
    virtual void initShape() // overridable
    {
      setName("Generic Shape");
    }

  private:
    std::string m_name;
};

Bu durumda, bir alt sınıf initShape işlevini bazı özel işler yapmak için geçersiz kılabilir :

class Square : public Shape
{
  public: 
    Square();
    virtual ~Square();

  protected:
    virtual void initShape() // override the Shape::initShape function
    {
      setName("Square");
    }
}

Terimi sanal saf bir alt sınıf tarafından uygulanması gereken ve temel sınıf tarafından uygulanan edilmemiştir sanal fonksiyonları ifade eder. Sanal anahtar sözcüğü kullanarak ve yöntem bildiriminin sonuna = 0 ekleyerek bir yöntemi salt sanal olarak belirlersiniz .

Yani, Shape :: initShape'i saf sanal yapmak istiyorsanız aşağıdakileri yaparsınız:

class Shape 
{
 ...
    virtual void initShape() = 0; // pure virtual method
 ... 
};

Sınıfınıza saf bir sanal yöntem ekleyerek, sınıfı , arabirimleri uygulamadan ayırmak için çok kullanışlı olan soyut bir temel sınıf haline getirirsiniz .


1
"Bir alt sınıf tarafından uygulanması gereken sanal işlevler" ile ilgili olarak - bu kesinlikle doğru değildir, ancak alt sınıf da değilse soyuttur. Ve soyut sınıflar somutlaştırılamaz. Ayrıca, "temel sınıf tarafından uygulanamaz" yanıltıcı görünüyor; Temel sınıf içinde bir uygulama eklemek için kod değişikliklerinde herhangi bir kısıtlama olmadığından "henüz" daha iyi olacağını öneriyoruz.
NVRAM

2
Ve "getName işlevi bir alt sınıf tarafından uygulanamaz" pek doğru değil. Alt sınıflar yöntemi uygulayabilir (aynı veya farklı imza ile), ancak uygulama yöntemi OVERRIDE yapmayacaktır. Circle'ı bir alt sınıf olarak uygulayabilir ve "std :: string Circle :: getName ()" uygulayabilirsiniz - o zaman bir Circle örneği için her iki yöntemi de çağırabilirsiniz. Ancak, bir Şekil işaretçisi veya başvuru yoluyla kullanılırsa, derleyici Shape :: getName () öğesini çağırır.
NVRAM

1
Her iki cephede de iyi puan. Bu örnek için özel durumları tartışmaktan uzak durmaya çalışıyordum, cevabı daha affedici olacak şekilde değiştireceğim. Teşekkürler!
Nick Haddad

@NickHaddad Old thread, ancak değişkeninizi neden çağırdığınızı merak ediyorsunuz m_name. Ne anlama m_geliyor?
Tqn

1
@Tqn, NickHaddad'ın sözleşmeleri izlediğini varsayarsak, m_name genellikle Macar notasyonu olarak adlandırılan bir adlandırma sözleşmesidir. M, bir yapının / sınıfın üyesini, tamsayıyı belirtir.
Ketcomp

16

"Sanal", yöntemin alt sınıflarda geçersiz kılınabileceği, ancak temel sınıfta doğrudan çağrılabilir bir uygulamaya sahip olduğu anlamına gelir. "Saf sanal", doğrudan çağrılabilen bir uygulaması olmayan sanal bir yöntem olduğu anlamına gelir. Bu tür bir yöntem olmalıdır en az kalıtım hiyerarşisinde bir kez geçersiz - bir sınıf, uygulanmamış sanal yöntemleri varsa, inşa edilemez bu sınıfın nesneler ve derleme başarısız olur.

Saf sanal yöntemler üzerinden @quark noktaları olabilir bir uygulama var, ama saf sanal yöntemleri geçersiz kılınan olmalı gibi varsayılan uygulama doğrudan denilen edilemez. Varsayılan olarak saf-sanal bir yöntem örneği:

#include <cstdio>

class A {
public:
    virtual void Hello() = 0;
};

void A::Hello() {
    printf("A::Hello\n");
}

class B : public A {
public:
    void Hello() {
        printf("B::Hello\n");
        A::Hello();
    }
};

int main() {
    /* Prints:
           B::Hello
           A::Hello
    */
    B b;
    b.Hello();
    return 0;
}

Yorumlara göre, derlemenin başarısız olup olmayacağı derleyiciye özgüdür. En azından GCC 4.3.3'te derlenmeyecektir:

class A {
public:
    virtual void Hello() = 0;
};

int main()
{
    A a;
    return 0;
}

Çıktı:

$ g++ -c virt.cpp 
virt.cpp: In function int main()’:
virt.cpp:8: error: cannot declare variable a to be of abstract type A
virt.cpp:1: note:   because the following virtual functions are pure within A’:
virt.cpp:3: note:   virtual void A::Hello()

sınıfın bir örneğini başlatmak istiyorsanız geçersiz kılınması gerekir. Herhangi bir örnek oluşturmazsanız, kod iyi derlenecektir.
Glen

1
derleme başarısız olmaz. (Saf) bir sanal yöntemin uygulanması yoksa, o sınıf / nesne somutlaştırılamaz. LINK olmayabilir, ancak derlenir.
Tim

@Glen, @tim: hangi derleyicide? Soyut bir sınıf oluşturan bir program derlemeye çalıştığımda, derlenmez.
John Millikin

@John Derleme yalnızca PVF içeren bir sınıf örneğini başlatmaya çalışırsanız başarısız olur. Elbette bu sınıflar için işaretçi veya referans değerleri başlatabilirsiniz.

5
Ayrıca, John, aşağıdakiler pek de doğru değil: "Saf sanal", uygulaması olmayan sanal bir yöntem olduğu anlamına geliyor. " Saf sanal yöntemlerin uygulamaları olabilir . Ancak bunları doğrudan çağıramazsınız: alt sınıf içinden temel sınıf uygulamasını geçersiz kılmanız ve kullanmanız gerekir. Bu, uygulamanın varsayılan bir bölümünü sağlamanıza olanak tanır. Yine de yaygın bir teknik değil.
quark

9

Sanal anahtar kelime nasıl çalışır?

İnsanın temel bir sınıf olduğunu, Hint'in insandan türediğini varsayın.

Class Man
{
 public: 
   virtual void do_work()
   {}
}

Class Indian : public Man
{
 public: 
   void do_work()
   {}
}

Do_work () öğesini sanal olarak bildirmek şu anlama gelir: çağrılacak do_work () işlevi SADECE çalışma zamanında belirlenecektir.

Varsayalım,

Man *man;
man = new Indian();
man->do_work(); // Indian's do work is only called.

Sanal kullanılmazsa, aynı nesne, hangi nesnenin çağırdığına bağlı olarak derleyici tarafından statik olarak belirlenir veya statik olarak bağlanır. Eğer bir Man nesnesi do_work () çağırırsa, Man's do_work (), BİR HİNTİN NESNESİNE ÇIKARILAR

En çok oy alan cevabın yanıltıcı olduğuna inanıyorum - Sanal olsun ya da olmasın herhangi bir yöntem türetilmiş sınıfta geçersiz kılınmış bir uygulamaya sahip olabilir. C ++ 'a özel atıfla, doğru fark çalışma zamanı (sanal kullanıldığında) bağlama ve derleme zamanıdır (sanal kullanılmaz, ancak bir yöntem geçersiz kılınır ve bir temel işaretçi türetilmiş bir nesneye işaret edilir) ilişkili işlevlerin bağlanmasıdır.

Başka bir yanıltıcı yorum var gibi görünüyor,

"Justin," saf sanal "yalnızca" bu işlev temel sınıf tarafından uygulanamaz "anlamına gelen bir terimdir (bir anahtar kelime değil, aşağıdaki cevabıma bakın).

BU YANLIŞ! Tamamen sanal işlevlerin de bir bedeni olabilir ve UYGULANABİLİR! Gerçek şu ki, soyut bir sınıfın saf sanal işlevi statik olarak çağrılabilir! Çok iyi iki yazar Bjarne Stroustrup ve Stan Lippman ... çünkü dili yazdılar.


2
Maalesef bir cevap onaylanmaya başladığında, diğerlerinin tümü göz ardı edilecektir. Tho bile daha iyi olabilirlerdi.
LtWorf

3

Sanal işlev, temel sınıfta bildirilen ve türetilmiş sınıf tarafından yeniden tanımlanan bir üye işlevdir. Sanal işlev miras sırasına göre hiyerarşiktir. Türetilmiş bir sınıf sanal bir işlevi geçersiz kılmadığında, temel sınıfında tanımlanan işlev kullanılır.

Saf sanal işlev, temel sınıfa göre tanım içermeyen bir işlevdir. Temel sınıfta bir uygulaması yoktur. Türetilmiş herhangi bir sınıf bu işlevi geçersiz kılmalıdır.


2

Varsayılan olarak statik yöntem bağlaması kullanan Simula, C ++ ve C #, programcı sanal olarak etiketleyerek belirli yöntemlerin dinamik bağlamayı kullanması gerektiğini belirtebilir. Dinamik yöntem bağlama, nesne yönelimli programlamanın merkezinde yer alır.

Nesneye yönelik programlama üç temel kavram gerektirir: kapsülleme, kalıtım ve dinamik yöntem bağlama.

Kapsülleme , bir soyutlamanın uygulama ayrıntılarının basit bir arayüzün arkasında gizlenmesini sağlar.

Kalıtım , yeni bir soyutlamanın, özelliklerinin bir kısmını veya tamamını otomatik olarak elde ederek mevcut bir soyutlamanın bir uzantısı veya iyileştirmesi olarak tanımlanmasını sağlar.

Dinamik yöntem bağlaması , yeni soyutlamanın, eski soyutlamayı bekleyen bir bağlamda kullanıldığında bile yeni davranışını görüntülemesini sağlar.


1

Sanal yöntemler sınıf türetilerek geçersiz kılınabilir, ancak temel sınıfta (geçersiz kılınacak olan) bir uygulamaya ihtiyaç duyar

Saf sanal yöntemlerin temel sınıf uygulaması yoktur. Türetilmiş sınıflar tarafından tanımlanmaları gerekir. (Teknik olarak geçersiz kılınan doğru terim değildir, çünkü geçersiz kılınacak bir şey yoktur).

Türetilmiş sınıf temel sınıfın bir yöntemini geçersiz kıldığında, sanal varsayılan java davranışına karşılık gelir.

Saf Sanal yöntemler soyut yöntemlerin soyut sınıflardaki davranışlarına karşılık gelir. Ve sadece saf sanal yöntemler ve sabitler içeren bir sınıf bir Arabirim için cpp-kolye olacaktır.


0

Saf Sanal İşlev

bu kodu dene

#include <iostream>
using namespace std;
class aClassWithPureVirtualFunction
{

public:

    virtual void sayHellow()=0;

};

class anotherClass:aClassWithPureVirtualFunction
{

public:

    void sayHellow()
    {

        cout<<"hellow World";
    }

};
int main()
{
    //aClassWithPureVirtualFunction virtualObject;
    /*
     This not possible to create object of a class that contain pure virtual function
    */
    anotherClass object;
    object.sayHellow();
}

Sınıfta anotherClass sayHellow işlevini kaldırın ve kodu çalıştırın. Bir sınıf saf bir sanal işlev içerdiğinde, o sınıftan hiçbir nesne oluşturulamaz ve bu devralındıktan sonra türetilmiş sınıfı bu işlevi uygulamalıdır.

Sanal işlev

başka bir kod dene

#include <iostream>
using namespace std;
class aClassWithPureVirtualFunction
{

public:

    virtual void sayHellow()
    {
        cout<<"from base\n";
    }

};

class anotherClass:public aClassWithPureVirtualFunction
{

public:

    void sayHellow()
    {

        cout<<"from derived \n";
    }

};
int main()
{
    aClassWithPureVirtualFunction *baseObject=new aClassWithPureVirtualFunction;
    baseObject->sayHellow();///call base one

    baseObject=new anotherClass;
    baseObject->sayHellow();////call the derived one!

}

Burada sayHellow işlevi temel sınıfta sanal olarak işaretlenir.Değişken sınıfta işlevi aramayı deneyen ve işlevi uygulayan derleyici der. Bulunamazsa temel olanı yürütün.


Haha, burada neyin yanlış olduğunu anlamak 30 saniyemi aldı ... Merhaba :)
hans

0

"Sanal işlev veya sanal yöntem, aynı imzaya sahip bir işlev tarafından devralınan bir sınıf içinde davranışı geçersiz kılınabilen bir işlev veya yöntemdir" - wikipedia

Bu sanal işlevler için iyi bir açıklama değildir. Çünkü bir üye sanal olmasa bile, sınıfların miras alınması onu geçersiz kılabilir. Kendiniz deneyebilirsiniz.

Bir fonksiyon parametre olarak bir temel sınıf aldığında fark kendini gösterir. Girdi olarak devralma sınıfı verdiğinizde, bu işlev geçersiz kılma işlevinin temel sınıf uygulamasını kullanır. Ancak, bu işlev sanal ise, türetme sınıfında uygulanan işlevi kullanır.


0
  • Sanal işlevlerin temel sınıfta ve ayrıca türetilmiş sınıfta bir tanımı olması gerekir, ancak gerekli değildir; örneğin, ToString () veya toString () işlevi Sanaldır, böylece kullanıcı tanımlı sınıf (lar) da geçersiz kılarak kendi uygulamanızı sağlayabilirsiniz.

  • Sanal işlevler normal sınıfta bildirilir ve tanımlanır.

  • Saf sanal işlev "= 0" ile biten bildirilmelidir ve yalnızca soyut sınıfta bildirilebilir.

  • Saf sanal işlev (ler) e sahip soyut bir sınıf, o saf sanal işlevlerin tanımına / tanımlarına sahip olamaz, bu nedenle uygulamanın o soyut sınıftan türetilen sınıf (lar) da sağlanması gerektiğini ima eder.


@Rashedcs ile aynı not: Gerçekten saf bir sanal fonksiyonun tanımı olabilir ...
Jarek C
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.