2011-01-10

C++のちょっと知られていないこと

他のクラスのメンバー関数を、friend関数にできる。

struct Y
{
    void f() ;
} ;

struct X
{
    friend void Y::f() ; // OK
} ;

このように、他のクラスのメンバー関数をfriend宣言することで、クラスすべてのメンバーではなく、あるメンバーだけを、friendとすることができる。

オーバーライドしたvirtual関数のアクセス指定は、オーバーライドされるvirtual関数には影響を及ぼさない。

class Base
{
public :
    virtual void f() { } // publicメンバー
} ;

class Derived : public Base
{
private :
    void f() { } // Base::fをオーバーライド、privateメンバー
} ;

int main()
{
    Derived d ;
    d.f() ; // エラー、Derived::fはprivateメンバー

    Base & ref = d ;
    ref.f() ; // OK、Derived::fを呼び出す
}

Base経由で、privateメンバーであるDerived::fを呼び出すことができる。これは、virtual関数のアクセスチェックは、呼び出す時点での宣言により、静的に決定されるためだ。関数mainから、Base::fにはアクセスできるため、ref.f()という式はエラーにならない。後は、通常通り、virtual関数呼び出しによって、オブジェクトの型である、Derivedのfが、正しく呼び出される。

もちろん、いま執筆中の参考書には、これらの仕様も漏れ無く説明されている。

2 comments:

  1. 似たような話で、gccやclangでこれが出来るのは何ででしょうね。なんかBCCだと公開水準を制限できないとか言って別のErrorになったような気がしますが。

    struct Base
    {
    static void Example();
    };

    class Derived:public Base
    {
    Base::Example;
    };

    Derived::Example();// Error

    ReplyDelete
  2. BCCのような古代のコンパイラーを使ってはいけません。
    その文法はAccess declarationといって、C++03ですらdeprecatedな文法です。使ってはいけません。
    かわりにusing declarationを使いましょう。

    ReplyDelete

You can use some HTML elements, such as <b>, <i>, <a>, also, some characters need to be entity referenced such as <, > and & Your comment may need to be confirmed by blog author. Your comment will be published under GFDL 1.3 or later license with no Invariant Sections, no Front-Cover Texts, and no Back-Cover Texts.