2012-04-18 8 views
1

Можно создать дубликат:
Public virtual function derived private in C++Почему функция-член все еще доступна, даже если она объявлена ​​как «закрытая»?

class B 
{ 
    private: 
    int b; 
    public: 
    B(int i); 
    virtual void show() 
    { 
     cout<<"B::show()called. "<<b<<endl; 
    } 
}; 

B::B(int i=0) 
{ 
    b=i; 
} 

class D:public B 
{ 
    private: 
    int d; 
    void show() 
    { 
     cout<<"D::show() called. "<<d<<endl; 
    } 
    public: 
    D(int i, int j); 
}; 

D::D(int i=0, int j=0):B(i) 
{ 
    d=j; 
} 

void fun(B&obj) 
{ 
    obj.show(); 
} 
/*if I redefine fun() as follow, the result would be the same 
void fun(B*obj) 
{ 
obj->show(); 
} 
*/ 
int main() 
{ 
    D *pd=new D(5,8); 
    fun(*pd);  //K 
    delete pd; 
} 

Выход программы "D :: шоу() называется.", Что означает виртуальную функцию, объявленную в закрытой части класса D. Вам не кажется странным? Как можно получить доступ к закрытому члену класса извне?

+5

Есть 999999 дубликатов этого вопроса. – Puppy

+0

Спецификаторы доступа ограничивают только те обращения, которые идут извне класса. Итак, если вы напишете удовольствие (D &) или удовольствие (D *), он не сможет получить доступ к D :: show(), используя статическую связь с конкретным классом братьев. Используя базовый класс, который имеет открытый член show(), вы получаете доступ через полиморфный вызов, который проходит через барьер для реализации брака. Ughh! :) Я просто попытался объяснить это более буквально. – parallelgeek

ответ

2

Это не странно. В B метод является общедоступным. Вы может позвонить show() на B объект.

Просто метод отправляется в расширяемый класс.

6

В отличие от Java, в C++ спецификатор доступа не влияет на функции virtual.
«Спецификатор доступа» - это проверка времени компиляции , которая производится по методу класса по отношению к типу дескриптора static. например в вашем коде obj имеет тип B и B::show() is public; следовательно, код является законным.
obj может относиться динамически к другому типу, кроме B.

Помните, что virtual функция отправки время выполнения явления. (В Java это дало бы ошибку времени выполнения.)

B::show()public это и как только он вызывается, то virtual функциональность будет удар и вызвать функцию соответствующего объекта в.

Если вы попытаетесь позвонить D::show() непосредственно, вы получите ожидаемую ошибку компилятора.

+0

«спецификатор доступа не влияет на виртуальные функции», вы, вероятно, должны отредактировать эту часть. Я понимаю, что вы имеете в виду, но это может ввести в заблуждение неподготовленный глаз. –

6

Важнейшая часть заключается в том, что ваша функция void fun(B&obj) принимает аргумент статического типа B& (поэтому преобразование происходит на сайте вызова, то же самое происходит с B*).

С B::showявляется общественностью, ваш код не имеет проблем со звонком. Когда компилятор смотрит, как отправить вызов, он видит, что show - virtual, поэтому он вызывает D::show. Тот факт, что вы не могли назвать D::show, если obj был типа D, не имеет значения.

+0

Я обнаружил, что если я поместил виртуальную функцию show() в личную часть базового класса B, программа не сможет скомпилировать, предупредив, что виртуальная функция является частной в базовом классе, даже если объявлена ​​копия в производном классе как public: #include using namespace std; класс A { private: virtual void function() {cout << "void A :: function() get invoked." << endl;} }; класс B: public A { public: void function() {cout << "void B :: function() get invoked." << endl;} }; int main() { \t \t B b; \t b.функция(); \t A * a = & b; \t A &ao=b; \t a-> function(); \t ao.function(); } – JDein