下面是访问实例的受保护字段x的一个微妙示例.B是A的子类,因此B类型的任何变量也是A类型.为什么B :: foo()可以访问b的x字段,而不是a的x字段?
class A {
protected:
int x;
};
class B : public A {
protected:
A *a;
B *b;
public:
void foo() {
int u = x; // OK : accessing inherited protected field x
int v = b->x; // OK : accessing b's protected field x
int w = a->x; // ERROR : accessing a's protected field x
}
};
Run Code Online (Sandbox Code Playgroud)
这是我用g ++得到的错误
$ g++ -c A.cpp
A.cpp: In member function ‘void B::foo()’:
A.cpp:3: error: ‘int A::x’ is …Run Code Online (Sandbox Code Playgroud) 我希望能够在我的包中有两个"受保护"类.也就是说,我不希望我的包外的文件看到它们是可见的 - 它们仅供包内部使用.
我怎样才能做到这一点?
我一直在尝试找到一种解决方法来在Objective-C中声明@protected属性,因此只有层次结构中的子类才能访问它们(只读,而不是写入).我读到没有记录的方法这样做,所以我想到了这个解决方法,我想问一下StackOverflow对它的看法.
层次结构顶部的每个自定义类都包含三个类,一个实现和两个接口.我们给它们命名:
ClassA.h
ClassA_protected.h
ClassA.m
Run Code Online (Sandbox Code Playgroud)
那么这个ClassA的任何子类都会像往常一样:
ClassB.h
ClassB.m
Run Code Online (Sandbox Code Playgroud)
首先,我创建了接口ClassA.h,其中我声明了一个受保护的int变量,因此ClassA的任何子类都可以访问它:
@interface ClassA : NSObject{
@protected
int _myProtectedInt;
}
@end
Run Code Online (Sandbox Code Playgroud)
下一步是我正在谈论的解决方法.但是,一旦你阅读它,你会发现它非常直接.我声明了第二个名为ClassA_protected.h的接口,它实际上是ClassA.h 的扩展,允许我们将属性标记为readonly:
#import "ClassA.h"
@interface ClassA ()
@property (nonatomic , readonly) int myProtectedInt;
@end
Run Code Online (Sandbox Code Playgroud)
准备受保护层次结构的最后一步是在ClassA.m中声明它的实现,我们只合成我们的属性:
#import "ClassA_protected.h"
@implementation ClassA
@synthesize myProtectedInt = _ myProtectedInt;
@end
Run Code Online (Sandbox Code Playgroud)
这样,每个需要成为ClassA.h子类的类都将导入ClassA_protected.h.因此,像ClassB.h这样的孩子如下:
#import "ClassA_protected.h"
@interface ClassB : ClassA
@end
Run Code Online (Sandbox Code Playgroud)
以及从ClassB.m的实现中访问此属性的示例:
@implementation ClassB
-(void) method {
//edit protected variable
_myProtectedInt= 1; …Run Code Online (Sandbox Code Playgroud) 这段代码:
abstract class C
{
protected abstract void F(D d);
}
class D : C
{
protected override void F(D d) { }
void G(C c)
{
c.F(this);
}
}
Run Code Online (Sandbox Code Playgroud)
生成此错误:
无法通过类型为"C"的限定符访问受保护的成员'CF(D)'; 限定符必须是'D'类型(或从中派生)
他们在想什么?(会改变那条规则会破坏某些东西吗?)除了让F公开之外,还有其他方法吗?
编辑:我现在明白为什么会这样(感谢格雷格),但我仍然对理性感到有些困惑; 给定:
class E : C
{
protected override void F(D d) { }
}
Run Code Online (Sandbox Code Playgroud)
为什么不应该 D是能够能够调用EF?
编辑错误消息,所以我可能会在那里输入错误.
如何可以在C++类中声明public,private或protected?
这是一个相当基本的OO问题,但是一段时间以来一直困扰着我.
我倾向于避免使用'private'可见性修饰符来支持我的字段和方法protected.
这是因为,一般来说,我没有看到在基类和子类之间隐藏实现的任何用法,除非我想为我的类的扩展设置特定的指导(即在框架中).对于大多数情况,我认为试图限制我的课程将由我或其他用户扩展是不利的.
但是,对于大多数人来说,private修饰符通常是定义非公共字段/方法时的默认选择.
那么,你可以列出用例private吗?总是使用私有的主要原因是什么?或者您是否也认为它过度使用?
这个问题出于好奇.是否有区别:
public abstract class MyClass
{
public MyClass()
{
}
}
Run Code Online (Sandbox Code Playgroud)
和
public abstract class MyClass
{
protected MyClass()
{
}
}
Run Code Online (Sandbox Code Playgroud)
谢谢.
为什么编译:
class FooBase
{
protected:
void fooBase(void);
};
class Foo : public FooBase
{
public:
void foo(Foo& fooBar)
{
fooBar.fooBase();
}
};
Run Code Online (Sandbox Code Playgroud)
但这不是吗?
class FooBase
{
protected:
void fooBase(void);
};
class Foo : public FooBase
{
public:
void foo(FooBase& fooBar)
{
fooBar.fooBase();
}
};
Run Code Online (Sandbox Code Playgroud)
一方面,C++为该类的所有实例授予对私有/受保护成员的访问权限,但另一方面,它不授予对所有子类实例的基类的受保护成员的访问权限.这看起来与我不一致.
我已经使用VC++和ideone.com测试了编译,并且编译了第一个但不是第二个代码片段.
我在package1中有一个名为A的类,在package2中有一个名为C的类.C类扩展了A类.
A有一个实例变量,声明如下:
protected int protectedInt = 1;
Run Code Online (Sandbox Code Playgroud)
这是A类的代码
package package1;
public class A {
public int publicInt = 1;
private int privateInt = 1;
int defaultInt = 1;
protected int protectedInt = 1;
}
Run Code Online (Sandbox Code Playgroud)
这是C类的代码:
package package2;
import package1.A;
public class C extends A{
public void go(){
//remember the import statement
A a = new A();
System.out.println(a.publicInt);
System.out.println(a.protectedInt);
}
}
Run Code Online (Sandbox Code Playgroud)
Eclipse强调了C.go()中的最后一行,并说"A.protectedInt"不可见.这似乎与oracle文档中给出的"protected"关键字的定义冲突.
protected修饰符指定只能在其自己的包中访问该成员(与package-private一样),此外,还可以在另一个包中通过其类的子类访问该成员.
这里发生了什么?
我已经看过有关protected和package private修饰符之间差异的各种文章.有一件事我发现这两个帖子之间存在矛盾
在这个被接受的答案说
protected修饰符指定只能在其自己的包中访问该成员(与package-private一样),此外,还可以在另一个包中通过其类的子类访问该成员.
在这个被接受的答案说
要满足受保护级别访问,必须满足两个条件:
- 这些类必须在同一个包中.
- 必须有继承关系.
他们不矛盾吗?根据我对其他文章的理解,第一篇文章给出了正确的答案,即在其他包中保护== package-private + subclass.
如果此语句是正确的,那么为什么此代码失败,并在第17行的子类Cat上出现以下错误消息
The method testInstanceMethod() from the type Animal is not visible
Run Code Online (Sandbox Code Playgroud)
我的超级和子类代码如下.
package inheritance;
public class Animal {
public static void testClassMethod() {
System.out.println("The class" + " method in Animal.");
}
protected void testInstanceMethod() {
System.out.println("The instance " + " method in Animal.");
}
}
package testpackage;
import inheritance.Animal;
public class Cat extends Animal{
public static void testClassMethod() {
System.out.println("The class method" + " in Cat."); …Run Code Online (Sandbox Code Playgroud) protected ×10
c++ ×3
java ×3
c# ×2
inheritance ×2
private ×2
public ×2
visibility ×2
class ×1
constructor ×1
objective-c ×1
oop ×1
overriding ×1
package ×1
properties ×1