2012-01-01 60 views
7

我想我知道平易的,但我不知道如果我理解的知名度很清楚班级成员的可见度?

例如:

class X 
{ 
    int x; 
}; 

在这里,“X”是只在课堂上,但访问外部可见的类。如果我是正确的,有人可以解释回答关于如何控制能见度的文本。

(C++ 03/11.0)应该注意的是,它是对成员和基类的访问,它控制着 而不是它们的可见性。成员的名字仍然是 可见,并且当基类不可访问时,隐式转换为基类仍然是 。建立给定结构的解释不考虑访问控制。如果所建立的解释使用 不可访问的成员名称或基类,则该结构为 不合格。

+0

您应该要求澄清该答案的评论。 – 2012-01-02 00:27:35

+1

@ TomalakGeret'kal:我会从我的问题中删除对该答案的引用。 – user1086635 2012-01-02 00:37:06

+1

恩......这与我所说的正好相反。 – 2012-01-02 00:56:26

回答

7

也许这个例子可以帮助:

class Bob 
{ 
private: 
    int foo(int, int); 
}; 

class David : Bob 
{ 
    void goo() { 
     int a = foo(1, 2); // #1 
    } 
}; 

class Dani : Bob 
{ 
    void foo(); 
    void goo() { 
     int a = foo(1, 2); // #2 
    } 
}; 

线#1,名称foo可见,但其名称的功能是不是(在账户被私下Bob访问)。这是一个编译错误,但编译器知道有一个可能的函数Bob::foo匹配,但不可访问。

线#2,名称foo仅指Dani::foo,而Bob::foo不可见(因为它是隐藏),所以根本就呼叫foo(1, 2)没有匹配的功能。这也是一个编译错误,但是这次错误是根本没有匹配的函数。

+1

我可以知道它会造成什么困惑吗? – user1086635 2012-01-02 00:45:19

+0

@ user1086635不确定你的意思在这里:行号只是不符合描述。 1号线是“鲍勃类”,但他似乎是“int foo(int,int);”而第2行是“{。”措辞需要编辑。 – Serodis 2012-01-02 01:15:45

+0

@Serodis:引用是用注释'//#1'等标记的行。这种注释风格在SO上是常见的做法,因为源块没有任何其他形式的易于看到的编号。 – 2012-01-02 01:19:38

7

C++有一些关于私有类成员名称可见性和可访问性的深奥特征。根据定义,私人类成员名称只能由班级成员和朋友访问。然而,可见性的规则可能会混淆许多。他们可以总结如下。

  1. 私人会员的名字只能被其他会员和朋友使用。
  2. 私有成员对于所有可以看到类定义的代码都是可见的。这意味着即使在这个翻译单元中永远不需要它的参数类型也必须声明它...
  3. 重载解析发生在可访问性检查之前。

在C++今日( “C++ 03” 和更早的变种),可达性和可见性的概念是 独立。只要“ 作用域”中的类和名称空间成员都可见,并且没有机制从声明的角度减少这种可见性。 辅助功能只是类成员的参数,与 可见性的概念正交。对于新手C++程序员来说,后一种观察常常令人惊讶。看到这个PDF

考虑下面的例子。

#include < complex> 

class Calc 
{ 
    public: 
     double Twice(double d); 
    private: 
     int Twice(int i); 
     std::complex Twice(std::complex c); 
}; 

int main() 
{ 
    Calc c; 
    return c.Twice(21); // error, Twice is inaccessible 
}  

当编译器将呼叫解析为一个功能,它做了三分主要的事情,依次是:

  • 之前做别的事情,对于一个作用域 具有在编译器搜索至少有一个名为Twice的实体,并列出候选人名单。 在这种情况下,名称查找首先查看Calc的范围,看看是否至少有一个名为Twice的函数 ;如果没有,基类 类和封装命名空间将依次考虑,一个在 时间,直到找到至少有一个候选人的范围。然而,在这个 的情况下,编译器看起来的第一个范围已经有一个名为Twice的实体 - 实际上它有三个,所以 三重奏变成了候选集合。 (有关C++名称 查找有关它如何影响你 应该打包的类和接口

  • 下一页方式的更多信息,与讨论中,编译器执行重载解析挑选独特 最佳匹配出来的在这种情况下,参数 是21,它是一个int,可用的重载需要一个double,一个 int和一个complex。显然int参数是int参数 的最佳匹配(它是完全匹配且没有转换需要 ),所以选择两次(int)。

  • 最后,编译器执行可访问性检查以确定 是否可以调用所选函数。

注意无障碍(由改性剂C++定义)和能见度是独立的。可见性基于C++的范围规则。一个班级成员可以是可见不可访问在同一时间。

静态成员作为例子是全局可见通过您的应用程序的运行,但只针对应用到它们的改性访问

1

作为一个说明:(而不是一个struct其中成员默认都是公共的)在声明class,范围是默认私人

可变构件“X”是的,只有你的类访问,它的朋友。没有其他人可以直接访问'x'(如果你有函数返回引用的话,它可以是间接的,这是一个非常糟糕的主意。)

你引用的文字谈到了编译器的可见性,所以X::x存在,不管是什么。它不会消失只是因为它是私人的。可见性用于查找您引用的成员,并返回匹配的第一个。在这一点上,编译器会检查可访问性,如果可以访问的话,你都很好。如果不是不合格

请注意,我提到的朋友。该关键字使所有可变成员都可访问。当编译器处理朋友时,它会完全忽略所有受保护的和专用的关键字。

在大多数情况下,这是一个非常简单的过程。它按顺序排列。期。

当你开始使用虚拟函数时,它们变得更加复杂:它们可以被公开,保护和私有,并且可以根据类声明而变化...(A派生自B并且产生受保护的虚函数公共;它通常不是一个好主意,但C++并不妨碍你这样做。)当然,这只适用于函数,而不是可变成员,所以这是一个不同的主题。