JavaからC++継承まで


この投稿は短くなりますが、特にJavaからC++に来る人々にとって役に立つかもしれません.今日、私は遺産をカバーしたいです.たぶん、そのコアではない-すべてのJava開発者がC +でそれを理解できるようになります.私は、それの意味論にもっと集中したいです.

スコープファースト
これは簡単なものですので、C +でスコープを開始しましょう.私たちにはC +の3つのスコープしかありません.そして、それは我々にすでに知られています.全く驚きません.パブリック(公共の意味)誰もが見える、保護されて保護されて-特定のクラスの子供だけがそのようなメンバーにアクセスすることができます.最後にプライベート修飾子があります-クラス内からのみアクセス可能なメンバーです.これまではすべてクリア.
その問題はコードに書き留めたときに起こります.Javaでは、クラスの前にアクセス修飾子を持つだけでなく、すべてのメソッドに対してもそれらを指定するために使用されています(インターフェイスの既定のパブリック修飾子を省略します.C +では、実際にはこのように見えるスコープセクションでクラスメンバをグループ化します.
class MyClass 
{
    public:
        int someMethod();

    protected:
        int someOtherMethod();

    private:
        int x, y;
}
彼らの命令は重要ではない.そして、それ以上のものがある.クラス以下ではうまくいきます.
class MyClass
{
    public:
        int someMethod();

    protected:
        int someOtherMethod();

    private:
        int x, y;

    public:
        int someMethod2();

    private:
        int z;
}
変な、右見て?正直なところ-私はまだ' C++のスタイルガイド'に達していないが、私はクラスの単一のスコープのセクションを使用するためのヒントがあることを期待.さあ、動きましょう.

遺産

スコープ継承
つのクラスから継承しているときは、演算子を使用する必要があります.同じ場所で、アクセス修飾子の一つを指定することができます.基本構造は次のようになります.
class Parent {};
class Child : ACCESS-MODIFIER Parent {};
アクセス修飾子の代わりに、既に知られている修飾子の1つを指定できます.修飾子が指定されていない場合、デフォルト値はprivateです.使用される修飾子に基づいて、継承されるクラスメンバーには次のアクセス修飾子があります.
  • パブリック
  • パブリックパブリックパブリック
  • 保護されたままの保護は

  • 個人的な
  • プライベート残り
  • 保護される
  • 人は、保護されて
  • になります
    保護されたままの保護は

  • 個人的な
  • プライベート残り
  • プライベート
  • パブリックは、私立
  • になります
    保護される
  • は、私立
  • になります
    個人的な
  • プライベート残り

  • メソッドの継承
    C +はOO言語ですので、明らかにメソッドの振る舞いの継承も必要です.しかし、Javaでは動作しません.例を見ましょう.
    class Parent {
        public void someMethod() {
            System.out.println("Parent");
        }
    }
    
    class Child extends Parent {
        public void someMethod() {
            System.out.println("Child");
        }
    }
    
    public static void main(String []args) {
        Parent p = new Parent();
        Child c = new Child();
        Parent referenceToChildUsingParent = c;
    
        p.someMethod();
        c.someMethod();
        referenceToChildUsingParent.someMethod();
    }
    
    コードは、できるだけ簡単です.親クラスにメソッドがある場合、子プロセスでスコープを制限しない場合は、継承してオーバーライドする必要はありません.出力は以下のようになります:
    Parent
    Child
    Child
    
    C +でそれは同じではない.上記のJavaコードの等価物は次のようになります.
    #include<iostream>
    
    class Parent {
        public:
            void say() {
                std::cout << "Parent says hi!" << "\n";
            }
    };
    
    class Child : public Parent {
        public:
            void say() {
                std::cout << "Child says hi!" << "\n";
            }
    };
    
    int main()
    {
        Parent parent;
        Child child;
        Parent& referenceToChildUsingParent = child;
    
        parent.say();
        child.say();
        referenceToChildUsingParent.say();
    }
    
    出力を推測できますか.はい、
    Parent says hi!
    Child says hi!
    Parent says hi!    // Yes, that's not a mistake!
    
    デフォルトでは、他の修飾子が指定されていない場合、' win 'の参照の型を指定します.Javaと同じ結果を得るためには、コンパイラが、派生クラスメソッド実装を使用したい場合は、コンパイラに指示しなければなりません.以下はコードです.
    #include<iostream>
    
    class Parent {
        public:
            virtual void say() {   // Notice the usage of VIRTUAL here
                std::cout << "Parent says hi!" << "\n";
            }
    };
    
    class Child : public Parent {
        public:
            void say() {
                std::cout << "Child says hi!" << "\n";
            }
    };
    
    int main()
    {
        Parent parent;
        Child child;
        Parent& referenceToChildUsingParent = child;
    
        parent.say();
        child.say();
        referenceToChildUsingParent.say();
    }
    
    現在の出力は同じです.Javaでの既定の修飾子に似た仮想的な動作-メソッドの現在の実装が親にあり、デフォルトで使用されます.ただし、メソッドが子クラスでオーバーライドされている場合は、使用されます.仮想クラスの使用は子供クラスのoverrideキーワードの使用で強化できます.Javaで@ overrideアノテーションのように動作します.このメソッドが継承されていることを示します.オーバーライドを使用する場合、親クラスで一致するメソッドシグネチャがない場合、コンパイラは失敗します.
    class Parent {};
    
    class Child : public Parent {
        public:
            void say() override {    // This line will cause compilation error
                std::cout << "Child says hi!" << "\n";
            }
    };
    
    Javaでは、デフォルトのキーワード(Java 8で導入され、インターフェイスにのみ適用)に加えて、古い古い抽象修飾子があります.リマインダーとして抽象クラスとして宣言されたクラス/メソッドはインスタンス化できません.構文は異なりますが、C +でも同じです.さらに、これらのタイプのメソッド(子供の具体的な実装を必要とする)-純粋な仮想メソッド/関数を呼び出します.見てみましょう
    #include<iostream>
    
    class Parent {
        public:
            virtual void say() =0;   // =0 is an equivalent of 'abstract'
    };
    
    class Child : public Parent {
        public:
            void say() override {
                std::cout << "Child says hi!" << "\n";
            }
    };
    
    int main()
    {
        //    Parent parent;   This line will cause compilation error when uncommented
        Child child;
        Parent& referenceToChildUsingParent = child;
    
        child.say();
        referenceToChildUsingParent.say();
    }
    
    この構文を使用すると、実際にC +でのインタフェース機能を実現することができますが、そのような概念はありません.ちょうどすべてのクラスメソッドを純粋なものと宣言してください、そして、それは手で芸術インターフェースの状態です.ここで重要なことは言及されなければなりません--それは良い実行です.そして、それはリソースが漏れるのを防ぐことができます-ベースクラス/インタフェースで常に仮想塵芥焼却炉を実装すること!それは十分です
    
    
    
    keyword for that - indicating that we let compiler generate the body of this method automatically.
    
    
    
    ```cpp
    class Parent {
    public:
        virtual void say() =0;
        virtual ~Parent() =default;
    };
    

    を、私のクラスのアクセス修飾子はどこですか?
    まあ、実際には、何もない.そうです.クラスアクセス修飾子の概念はありません.クラスはすべて決められる
    メンバーレベルは、我々はそれについてできることは何もありません.Javaの世界から来る巨大な制限のようです.しかし、C++ 20で導入されたC +モジュールのコンセプトは、ここで役立つようですが、私はまだそれに飛び込みたくありません.私は、将来それについて別々のポストを書く予定を持ちます.

    友人関数
    '友達を話すと'を入力する権利を右に来るか?再び-私はC +でこの概念を発見することに驚いた.それはJavaでのパッケージプライベート修飾子のようなものです.要するに-フレンド機能は、実際には、そのメンバーのメンバーではありませんが、クラスのプライベートと保護された要素にアクセスすることができます.ワット?yup、あなたはそれを正しく読んでください.この機能は、以下の例よりも複雑になっていますが(公式CPP参照から取って)、コードの下にこの概念に若干の光を当てるべきです.
    class Y {
        int data; // private member
        // the non-member function operator<< will have access to Y's private members
        friend std::ostream& operator<<(std::ostream& out, const Y& o);
        friend char* X::foo(int); // members of other classes can be friends too
        friend X::X(char), X::~X(); // constructors and destructors can be friends
    };
    
    // friend declaration does not declare a member function
    // this operator<< still needs to be defined, as a non-member
    std::ostream& operator<<(std::ostream& out, const Y& y)
    {
        return out << y.data; // can access private member Y::data
    }
    
    ソース

  • ジョシュLospinoso ' C++クラッシュコース'帳
  • friend functions and objectsについての
  • CPPリファレンス

  • あなたが友人機能
  • を使用しなければならないときSO question