班级成员的可见度?

时间:2012-01-01 23:44:40

标签: c++ scope visibility

我想我知道可以接受,但我不确定我是否能清楚地了解能见度

例如:

class X
{
   int x;
};

在这里,'x'仅在课堂上可见,但在课堂外可以访问。如果我是正确的,有人可以在回答中解释关于如何不控制可见性等的文本。?

  

(C ++ 03 / 11.0)应该注意,它是对成员和基类的访问   被控制,而不是他们的能见度。成员姓名仍然是   对基类的可见和隐式转换仍然存在   当这些成员和基类无法访问时。该   建立对给定构造的解释而不考虑   访问控制。如果建立的解释利用   不可访问的成员名称或基类,构造是   不良形成。

4 个答案:

答案 0 :(得分: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 可见,但它所指定的功能无法访问(由于对{{{ 1}})。这是一个编译错误,但编译器知道有一个潜在的函数Bob可以匹配,但是不可访问。

在第2行,名称Bob::foo仅指foo,而Dani::foo 不可见(因为它隐藏),因此调用Bob::foo根本没有匹配函数。这也是一个编译错误,但这次错误是该调用根本没有匹配函数。

答案 1 :(得分:7)

C ++有一些关于私有类成员名称可见性和可访问性的深奥功能。根据定义,私有类成员名称只能由类成员和朋友访问。然而,可见度规则可能会使许多人感到困惑。它们可归纳如下。

  1. 只有其他会员和朋友才能访问私人会员的姓名。
  2. 查看类定义的所有代码都可以看到私有成员。这意味着必须声明其参数类型,即使在此翻译单元中永远不需要它们...
  3. 在可访问性检查之前发生过载解决。
  4.   

    在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的函数;如果没有,基地 将依次考虑类和封闭的命名空间,一个在a 时间,直到找到至少有一个候选人的范围。在这 但是,编译器看起来已经具有的第一个范围 一个名为Twice的实体 - 事实上,它有三个,所以 三人成为候选人。 (有关名称的更多信息 在C ++中查找,讨论它如何影响你的方式 应打包您的类及其接口

    • 接下来,编译器执行重载决策以选择唯一 候选人名单中的最佳匹配。在这种情况下,论证 是21,这是一个int,可用的重载需要一个双,一个 int和一个复杂的。显然,int参数是最佳匹配 int参数(它是完全匹配,没有转换 需要),所以选择了两次(int)。

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

    请注意,辅助功能(由C ++中的修饰符定义)和可见性是独立的。可见性基于C ++的范围规则。类成员可以同时可见无法访问

    静态成员作为示例在运行应用程序时全局可见,但仅可访问仅适用于应用于它们的修饰符。

答案 2 :(得分:1)

作为注释:当您声明class时,默认情况下范围是私有的(与struct相对,默认情况下成员是公共的。)

变量成员'x'只能由您的班级及其朋友访问。没有其他人可以直接访问'x'(如果你有一个函数返回对它的引用,它可以间接访问它,这是一个非常糟糕的主意。)

您引用的文字讨论了编译器的可见性,因此X::x存在,无论如何。它不会消失只是因为它是私有的。可见性用于查找您引用的成员,并返回匹配的第一个成员。此时,编译器会检查可访问性,如果可访问,那么一切都很好。如果不是格式错误

请注意,我提到了朋友。该关键字使所有变量成员都可访问。当编译器与朋友交易时,它会完全忽略所有受保护和私有关键字。

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

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

答案 3 :(得分:0)

可访问性和可见性是独立的,这在以下情况下尤其令人困惑:

class A
{
public:
  void Foo(int i){
  }
};

class B : public A
{
private:
  void Foo(){
  }
};

int main(){
    B b{};

    b.Foo(12);
}

其他语言的程序员希望A::Foo(int)是可调用的,因为它是公共的。这里的重点是,私有B::Foo隐藏了继承的proc。

这可以通过使用声明using A::Foo来解决。但是在这种情况下真的变得很困难:

class A
{
public:
  void Foo(int i){
  }
};

class B : public A
{
public:
  using A::Foo;
private:
  void Foo(){
  }
};


class C : public B
{
public:
  using B::Foo;
private:
  void Foo(char c){
  }
}

int main(){
    B b{};

    b.Foo(12);
}

使用要求没有私有功能。 AFAIK解决此问题的最佳方法是为私有或受保护的函数(例如do_XXX()或do_XXX_internal)使用一些前缀/后缀。

在STL中,私有成员通常以单个下划线作为前缀(这些是保留的标识符)。

相关问题