blog

C++コア構文

C++の基本的な知識があれば、C++チュートリアルを始めるのに最適な方法ですC++チュートリアル - C++を始める名前空間とは名前空間は、複数のモジュール間の名前の競合の問題を解決するために使用され...

Oct 25, 2020 · 9 min. read
シェア

C++は、C言語の基本的な知識を持っている人が始めるのに適しています。

C++チュートリアル

    名前空間とは

    名前空間は、モジュール間の名前の衝突を解決するために使用されます。

    #include <iostream>
    using namespace std;
    int main() {
     cout<<"*******"<<endl;
     cout<<"Hello World!"<<endl;
     cout<<"*******"<<endl;
     return 0;
    }
    

    ドメイン修飾子 :: を 使うことで、ケースバイケースで数を指定することもできます

    #include <iostream>
    //using namespace std;
    int main() {
     std::cout<<"*******"<<std::endl;
     std::cout<<"Hello World!"<<std::endl;
     std::cout<<"*******"<<std::endl;
     return 0;
    }
    

    入力と出力

    • coutは<< />付き
    • cin with >>はキーボードからの入力を読み込むことを意味します。
    #include <iostream>
    using namespace std;
    int main() {
     int a;
     cout<<"input string"<<endl;
     cin>>a;
     cout<<"get string is "<<a<<endl;
     return 0;
    }
    

    出力は

    input string
    123
    get string is 123
    

    基本的なデータ型

    • int、char、float、doubleは、それぞれプラスチック、文字、単精度、倍精度を表します。
    • Cよりも、ブール型boolがあり、1は真、0は偽を意味します。
    #include <iostream>
    using namespace std;
    int main() {
     int id;
     char sex;
     double score1 = 0, score2 = 0, score3 = 0;
     bool isNO1;
     cout << "please input ID, 'M' or 'W', score1, score2, score3" << endl;
     cin >> id >> sex >> score1 >> score2 >> score3;
     isNO1 = score1 > 12;
     cout << "ID=" << id << ",sex=" << sex << ",total=" << score1 + score2 + score3 <<",isNo1="<<isNO1<<endl;
     return 0;
    }
    

    演算子と式

    • 算術演算子 +, -, *, %。
    • 自己増加・自己減少演算子 ++, --。
    • 代入演算子 =
    • <、>関係演算子 >、=、<=、!=, ==
    • 論理演算子 && || !
    /**
     * 数値が"水仙の数" "水仙の数"は、まず3桁の数字である。
     * 次に、その数字の3乗和は数字そのものに等しい。例えば、371は"水仙の数" +7^3+1^3.
     * @return
     */
    int main() {
     int a, ge, shi, bai;
     cout << "input num >100" << endl;
     cin >> a;
     ge = a % 10;
     shi = a % 100 / 10;
     bai = a / 100;
     cout << "ge=" << ge << ",shi=" << shi << ",bai=" << bai << endl;
     if ((ge * ge * ge + shi * shi * shi + bai * bai * bai) == a) {
     cout << 1 << endl;
     } else {
     cout << 0 << endl;
     }
     return 0;
    }
    

    出力は

    input num >
    ge=9,shi=8,bai=7
    

    ループ構造

    forループ、do whileループ、whileループ、breakとcontinueの組み合わせ

    #include <iostream>
    using namespace std;
    int main() {
     int a,b;
     while (cin>>a>>b){
     cout<<a+b<<endl;
     }
     return 0;
    }
    

    cinはistreamストリーム・オブジェクトを返すので、何度でもトラバースすることができます。

    1 2
    3
    4 5
    9
    7 8
    15
    ...
    

    関数呼び出し

    #include <iostream>
    #include <cstring>
    using namespace std;
    /**
     * 文字列の反転 123abc---->cba321
     * @param a オリジナルの文字列
     * @param b 反転文字列
     * @return
     */
    int reverse(char a[], char b[]) {
     int n = strlen(a);
     int i = 0;
     while (a[i] != '\0') {
     b[n - i - 1] = a[i];
     i++;
     }
     b[n] = '\0';
     return 0;
    }
    int main() {
     char a;
     char b;
     cin >> a;
     reverse(a, b);
     cout << b << endl;
     return 0;
    }
    

    デフォルトの形式パラメータを持つ関数

    形式パラメータは、デフォルトの関数

    int main() {
     cout<<add()<<endl;
     cout<<add(1,9)<<endl;
     cout<<add(5)<<endl;
     return 0;
    }
    

    オーバーロードされた関数

    Javaと同様に、C++の関数もオーバーロードすることができます。

    int add(int a = 2, int b = 6) {
     return a + b;
    }
    double add(double a = 1, double b = 5) {
     return a + b;
    }
    

    関数テンプレート

    javaのジェネリックスと同様に、テンプレートで定義されます。

    #include <iostream>
    using namespace std;
    template<class T1, class T2>
    T1 add(T1 a, T2 b) {
     cout << sizeof(a) << " , " << sizeof(b) << "\t";
     return a + b;
    }
    int main() {
     cout << add(1, 5) << endl;
     cout << add(1.2, 1.5) << endl;
     cout << add('A', 2) << endl;
     return 0;
    }
    
    4 , 4 6 8 , 8 2.7 1 , 4 C

    インライン関数

    関数のメソッドスタック呼び出し時に、呼び出しの時点で関数を完全に展開することで、スペースと時間を節約します。

    inline int Max(int a, int b) {
     return a > b ? a : b;
    }
    int main() {
     cout << Max(1, 2) << endl;
     cout << Max(6, 5) << endl;
     return 0;
    }
    

    クラスとオブジェクト

    ドメイン修飾子

    クラス名の外にあるメソッドは、ドメイン修飾子 :: で定義されますが、最初にクラス内で関数名を定義する必要があります。

    class Person {
    public:
     int num;
     char name;
     double score;
     int print();
    };
    int Person::print() {
     cout << num << " " << name << " " << score << endl;
     return 0;
    }
    

    と同じです。

    class Person {
    public:
     int num;
     char name;
     double score;
     int print() {
     cout << num << " " << name << " " << score << endl;
     return 0;
     }
    };
    

    コンストラクタ

    C++ にはデフォルトのコンストラクタがありますが、カスタマイズすることもできます。

    class Student {
    private:
     char name;
     int num;
     double score;
    public:
     Student(char *n, int num1, double score1);
     void print();
    };
    Student::Student(char *n, int num1, double score1) {
     strcpy(name, n);
     num = num1;
     score = score1;
    }
    void Student::print() {
     cout<<name<<" "<<num<<" "<<score<<endl;
    }
    int main() {
     Student A("xiaoming", );
     A.print();
     return 0;
    }
    

    デストラクタ

    • 関数の前に ~ を追加します。
    • デフォルトの関数はカスタマイズすることもでき、オブジェクトが破棄されるときに呼び出されます。
    class Student {
    private:
     char name;
     int num;
     double score;
    public:
     Student(char *n, int num1, double score1);
     ~Student();
     void print();
    };
    Student::Student(char *n, int num1, double score1) {
     strcpy(name, n);
     num = num1;
     score = score1;
     cout << name << " " << num << " " << score << " constructor" << endl;
    }
    Student::~Student() {
     cout << name << " " << num << " " << score << " destructor" << endl;
    }
    void Student::print() {
     cout << name << " " << num << " " << score << endl;
    }
    int main() {
     Student A("this is A", );
     Student B("this is B", );
     return 0;
    }
    
    this is A 1 98.7 constructor
    this is B 2 98.6 constructor
    this is B 2 98.6 destructor
    this is A 1 98.7 destructor
    

    BのデストラクタはAの前に呼ばれます。ローカル変数はスタック上にあるので、「先入れ先出し」の原則に従います。

    コピーコンストラクタ

    オブジェクト参照を関数のパラメータとして受け取ります。

    class Circle {
    private:
     double R;
    public:
     Circle(double R);
     Circle(Circle &circle);
    };
    Circle::Circle(double R) {
     cout<<"constructor"<<endl;
     this->R = R;
    }
    Circle::Circle(Circle &circle) {
     cout<<"copy constructor"<<endl;
     this->R = circle.R;
    }
    int main() {
     Circle A(2);
     Circle B(A);
     return 0;
    }
    

    デフォルトのコピーコンストラクタはシャローコピーで、カスタムのものはディープコピーです。 シャローコピーは値を変更し、ディープコピーはメモリアドレスを変更します。

    フレンドリー関数

    このクラスの関数に他の関数からアクセスしたい場合は、friend を使ってその関数を friend としてマークすることができます。

    class Point {
    private:
     double x;
     double y;
    public:
     Point(double x, double y) {
     this->x = x;
     this->y = y;
     }
     friend double getD(Point &a, Point &b);
    };
    double getD(Point &a, Point &b) {
     double xx = a.x - b.x;
     double yy = a.y - b.y;
     return sqrt(xx * xx + yy * yy);
    }
    int main() {
     Point A(1.0, 2.0);
     Point B(2.0, 3.0);
     double l = getD(A, B);
     cout<<l<<endl;
     return 0;
    }
    

    friend をつけないと、main 関数の中で getD 関数を呼び出すことができません。

    フレンド

    クラスBがクラスAのフレンドとして定義されている場合、BはAのプライベート変数にアクセスできます。

    class Point {
    private:
     double x;
     double y;
    public:
     Point(double x, double y) {
     this->x = x;
     this->y = y;
     }
     friend class Tool;
    };
    class Tool {
    public:
     double getD(Point &point) {
     double l = sqrt(point.x * point.x + point.y * point.y);
     cout<<l<<endl;
     return l;
     }
    };
    int main() {
     Point C(1.0, 2.0);
     Tool tool;
     tool.getD(C);
     return 0;
    }
    

    定数

    I.定数データ・メンバ

    • 例えば、int h は const int h または int const h と表示されます。
    • 定数メンバ変数は、コンストラクタでデフォルト値を指定する必要があります。
     Clock(int a) : h(a){
     cout<<"constructor"<<endl;
     }
    
    • static で指定した const は、クラスの外で代入する必要があります。
    class Clock{
    private:
     const int h;
     const int m;
     int const s;
     static const int x;
    public:
     Clock(int a,int b, int c) : h(a), m(b), s(c) {
     cout<<"constructor"<<endl;
     }
     int getX() {
     cout<<x<<endl;
     return x;
     }
    };
    const int Clock::x = 99;
    int main() {
     Clock A(1, 2, 3);
     A.getX();
     return 0;
    }
    

    II.定数オブジェクト

    コンスタントオブジェクトもまた、ライフサイクル中は不変であり、コンストラクタを通して値を代入することができます。

     const Clock A(1, 2, 3);
     //A.getX(); この行はエラーを報告する
    

    III.定数関数

    • 定数関数はメンバ変数にのみアクセスでき、書き換えることはできません。
     int getX() const {
     //x=66;  
     cout << x << endl;
     return x;
     }
    

    継承と派生

    継承

    • 継承は親クラス、派生は子クラスです。
    • 継承はコロン
    class Person {
    protected:
     char name;
     int sex;
    public:
     void setName(char *n) {
     strcpy(name, n);
     }
    };
    class Student: public Person {
    public:
     void setSex(int s) {
     this->sex = s;
     }
     void getInfo() {
     cout<<name<<" "<<sex<<endl;
     }
    };
    int main() {
     Student A;
     A.setName("tanakasan");
     A.setSex(0);
     A.getInfo();
     return 0;
    }
    

    派生クラスのコンストラクタ

    まず親クラスのコンストラクタを呼び出し、次に子クラスのコンストラクタを呼び出します。

    #include <iostream>
    #include <cstring>
    using namespace std;
    class Person{
    public:
     char name;
     int sex;
    public:
     Person(char *name,int sex) {
     strcpy(this->name, name);
     this->sex = sex;
     cout<<"Person contructor"<<endl;
     }
    };
    class Student: public Person {
    public:
     Student(char *n, int o) : Person(n, o) {
     cout<<"Student contructor"<<endl;
     }
    };
    int main() {
     Student A("xiaoming", 1);
     return 0;
    }
    

    スタックの先入れ先出しの原則により、デストラクタは逆に呼ばれます。つまり、子クラスが最初に呼ばれ、次に親クラスが呼ばれます。

    仮想基底クラス

    C++ では多重継承が可能ですが、複数の親クラスから継承する場合、親クラスに virtual を追加する必要があります。

    class A {
    public:
     int key;
    };
    class B: virtual public A {
    };
    class C: virtual public A {
    };
    class D : public B, public C {
    };
    int main() {
     D d1;
     d1.key = 6;
     return 0;
    }
    

    仮想関数

    仮想関数はポリモーフィックな問題を解決するために使用されます。

    class Point {
    private:
     int x;
     int y;
    public:
     Point(int x = 0, int y = 0) {
     this->x = x;
     this->y = y;
     }
     virtual double area() {
     return 0;
     }
    };
    class Circle: public Point {
    private:
     int x1;
     int x2;
     int x3;
    public:
     Circle(int d,int e, int f) {
     this ->x1 = d;
     x2 = e;
     x3 = f;
     }
     double area() {
     return 3.14 * x1 * x2;
     }
    };
    int main() {
     Point A(10, 11);
     cout<<A.area()<<endl;
     Circle B(2, 6, 7);
     cout<<B.area()<<endl;
     Point *D;
     D = &B;
     cout<<D->area()<<endl;
     Point &p = B;
     cout<<p.area()<<endl;
     return 0;
    }
    

    仮想デストラクタ関数

    基底クラスのデストラクタにダミー関数を追加することで、そのサブクラスのダミー関数も呼び出すことができます。

    Read next

    Vue SSR vignetteはどのようにルーティングするのか?

    サーバコードでは、任意の URL を受け付ける * ハンドラをリクエストに使用します。 この URL を Vue に渡すことで、Vue のルーティングを操作できます。 ルータは、ルーティング設定内の非同期コンポーネントを事前に解析する必要があるため、マウント内でアプリを呼び出す必要があることに注意してください。

    Oct 24, 2020 · 2 min read