C++核心语法

429 阅读2分钟

有C语言的基础,C++很好入门

C++教程

什么是命名空间namespace

命名空间是为了解决多个模块之间命名冲突的问题

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

其中count也可以通过域限定符 :: 来逐个制定

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

输入和输出

  • cout搭配<<表示输出,可使用多个<<,endl表示换行
  • cin搭配>>表示读取从键盘的输入
#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表示true,0表示flase
#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;
}

运算符和表达式

  • 算术运算符 +、-、*、%
  • 自增自减运算符 ++、--
  • 赋值运算符 =
  • 关系运算符 >、<、>=、<=、!=、==
  • 逻辑运算符 &&、||、!
/**
 * 判断一个数是否为"水仙花数",所谓"水仙花数"是指这样的一个数:首先是一个三位数,
 * 其次,其各位数字的立方和等于该数本身。例如:371是一个"水仙花数",371=3^3+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 >100
789
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[100];
    char b[100];
    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中的泛型,通过template来定义

#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

节省了函数的方法栈调用过程中的空间和时间,将函数完全展开在调用处

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;
}

类和对象

1.域限定符::

类名外的方法通过域限定符::来定义,但要在类中先定义好函数名称

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

相当于

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

2.构造函数

C++有默认构造函数,也可以自定义

class Student {
private:
    char name[100];
    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", 01, 98.7);
    A.print();
    return 0;
}

3.析构函数

  • 函数前要加~
  • 有默认函数,也可以自定义,随对象的销毁而调用
class Student {
private:
    char name[100];
    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", 01, 98.7);
    Student B("this is B", 02, 98.6);
    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先调用,因为局部变量在一个栈中,遵循“先进后出”的原则

4.拷贝构造函数

将对象引用作为函数的参数

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;
}

默认的拷贝构造函数是浅拷贝,自定义的是深拷贝,浅拷贝改变的是值,深拷贝改变的是内存地址

5.友元函数

在其他函数中,访问该类的函数,可以将该函数通过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函数的

6.友元类

如果class B定义为class 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;
}

7.常数

一.常数据成员

  • 比如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;
}

二.常对象

常对象同样在生命周期内不可改变,可以通过构造函数赋值

 const Clock A(1, 2, 3);
 //A.getX(); 这行会报错

三.常函数

  • 常函数只能访问成员变量,不可改写
 int getX() const {
        //x=66; 报错
        cout << x << endl;
        return x;
    }

继承与派生

继承

  • 继承面向父类,派生面向子类
  • 通过冒号实现继承
class Person {
protected:
    char name[100];
    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("zhangsan");
    A.setSex(0);
    A.getInfo();
    return 0;
}

派生类的构造函数

先调父类的构造函数,再调子类的构造函数

#include <iostream>
#include <cstring>
using namespace std;
class Person{
public:
    char name[100];
    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;
}

虚析构函数

通过给基类析构函数添加虚函数,来实现也调用其子类虚构函数的目的