Все это хорошие ответы. Я хотел бы добавить пример выполнения при передаче объектов по значению vs по ссылке:
#include <iostream>
using namespace std;
// Base class
class A {
public:
A() {}
A(const A& a) {
cout << "'A' copy constructor" << endl;
}
virtual void run() const { cout << "I am an 'A'" << endl; }
};
// Derived class
class B: public A {
public:
B():A() {}
B(const B& a):A(a) {
cout << "'B' copy constructor" << endl;
}
virtual void run() const { cout << "I am a 'B'" << endl; }
};
void g(const A & a) {
a.run();
}
void h(const A a) {
a.run();
}
int main() {
cout << "Call by reference" << endl;
g(B());
cout << endl << "Call by copy" << endl;
h(B());
}
Выход:
Call by reference
I am a 'B'
Call by copy
'A' copy constructor
I am an 'A'
Что здесь происходит?
blockquote>Вы неправильно поняли значение
protected
. Вы можете получить доступ к защищенным членам, объявленным вA
, изC
, но только для экземпляровC
или подклассовC
. Подробнее о защищенном доступе см. В разделе 6.6.2 раздела JLS . В частности:Пусть C - класс, в котором объявлен защищенный член. Доступ разрешен только внутри тела подкласса S из C.
Кроме того, если Id обозначает поле экземпляра или метод экземпляра, то:
blockquote>
- [... ]
- Если доступ осуществляется с помощью выражения доступа к полю E.Id, где E является первичным выражением или выражением вызова метода E.Id (...), где E является первичным выражением, то доступ разрешен тогда и только тогда, когда тип E является S или подклассом S.
(Emphasis mine.)
Итак этот код был бы точным:
C c = new C(); System.out.println(c.publicInt); System.out.println(c.protectedInt);
public void go(){
//remember the import statement
A a = new A();
System.out.println(a.publicInt);
System.out.println(a.protectedInt);
}
Когда вы делаете A a = new A();
и a.protectedInt
, вы пытаетесь получить доступ к защищенному члену A, который является незаконным в соответствии со стандартами java
. Вместо этого вы можете делать this.protectedInt
напрямую.
Защищенные средства:
a) Этот член будет доступен для всех классов в одном пакете с помощью ссылки объекта.
b) Для другого пакета это будет доступно только внутри Подклассы A говорят B и используемая ссылка могут быть экземплярами B или любого подкласса B.
Возьмем пример:
Пусть A - родительский класс в некотором пакете, скажем com.ex1
Пусть B, C - классы в разных пакетах по A say com.ex2
. Кроме того, B extends A
и C extends B
. Мы увидим, как мы можем использовать защищенное поле A внутри B (подкласс A)
Код A:
public class A {
protected int a = 10;
}
Код B:
public class B extends A {
public void printUsingInheritance() {
// Using this
System.out.println(this.a);
}
public void printUsingInstantiation() {
// Using instance of B
B b = new B();
System.out.println(b.a);
// Using instance of C as C is subclass of B
C c = new C();
System.out.println(c.a);
A a = new A();
System.out.println(a.a); // Compilation error as A is not subclass of B
}
}
Код C:
public class C extends B {
}
Для защищенных статических:
Те же правила применяются, за исключением того, что в b) теперь он доступен в любом подклассе класса A по ссылке класса A. [Д0] Ссылка
В том же пакете, где объявлен защищенный член, разрешен доступ:
package package1;
public class C extends A{
public void go(){
A a = new A();
System.out.println(a.protectedInt); // got printed
C c = new C();
System.out.println(c.protectedInt); // got printed as well
}
}
Вне пакета, в котором объявлен защищенный член, доступ разрешен тогда и только тогда, когда по коду, который отвечает для реализации этого объекта. В этом случае C отвечает за реализацию этого объекта, поэтому он может получить доступ к защищенным.
package package2;
public class C extends A{
public void go(){
A a = new A();
System.out.println(a.protectedInt); // compiler complains
C c = new C();
System.out.println(c.protectedInt); // got printed
}
}
Не нужно создавать экземпляр класса защиты внутри класса Protection2. Вы можете напрямую вызвать защищенную переменную без создания экземпляра класса защиты. Поскольку класс Protection2 расширяет класс защиты. Таким образом, переменная автоматически унаследована подклассом.
Попробуйте использовать код ниже:
public class Protection2 extends Protection{
Protection2()
{System.out.println("n_pro = " +n_pro);
}}
protected
, нет - если бы это была видимость по умолчанию (пакет) илиprivate
, это было бы не видно. – Jon Skeet 2 September 2013 в 14:34E
здесьA
, аS
-C
. ХотяC
является подклассомA
,A
не является i> подклассомC
. – Jon Skeet 2 September 2013 в 17:49