0%

c++学习笔记

四大件

  1. 数据结构和算法
  2. 计算机网络
  3. 操作系统
  4. 设计模式组成原理

数据类型

  1. 常量

    ​ 宏常量 #define

    ​ const 修饰变量

    ​ 均不可修改

  2. 字符串

    char str[] = “ldksjfa”,会默认多一个’\0’

    string str = “dlkjafd” 需要头文件

  3. bool char int float double void wchar_t

  4. typedef为已有类命新名字

    typedef int feet;
    feet a = 1;

运算符

  1. 三目运算符可以返回变量也可以返回变量值

控制结构

  1. if - else if - else
  2. switch - case break- case break-default break 只能是int 或者 char,必须break
  3. 循环结构 while(){},do{}while(),for(int i =0;i<10;i++)
  4. goto FLAG; FLAG:
  5. continue

数组

一维数组

  1. 定义数组

    1. int a[10];
    2. int a[10] = {0,1,2,3,4,5,6,7,8,9}
    3. int a[] = {0,1,2,3}
  2. 特点

    1. 数据类型相同
    2. 内存空间连续
  3. 赋值

    int a[10] = {0}; //初始化表长度小于要被初始化的数组的元素数目,剩余元素均为0;
  1. 注意

    int n;
    cin >> n;
    int a[n]; //这是错误的写法,尽管有些编译器可能不会报错

    int b[0]; //长度为0的数组没有任何意义

    int c[10];
    cout<<c[11]; //越界但可以输出
  2. 排序查找

    选择排序

    冒泡排序

二维数组

  1. 初始化赋值

    int a[10][10] = {{1,2}, {2,3}, {3,3,4,4}};
    int a[][10] = {{},{}}
  1. 注意
    1. 行数
    2. 元素数目(用好sizeof())
    3. 理解好变量名与地址的关系

字符串

  1. 初始化

    char ch[] = {'h','e','l','l','o','\0'};
    char ch[] = {"hello"};
    char ch[] = "hello";
    char ch[] = "hello"; //这是错误的
    char ch[10] = "hello"; //后面的字符都是'\0','\0'是不可显示的
    char ch[6] = {'h', 'e', 'l', 'l', 'o'} //是字符串
    char ch[5] = {'h', 'e', 'l', 'l', 'o'} //不是字符串
  2. 空字符串

    char ch[] = ""; //占用一个字节存储'\0'
    //'a'与"a",前者是简单的变量,后者是数组
  3. 遍历

    forint i = 0; str[i]!='\0'; i++)
    {
    cout<<str[i];
    }
  4. 输入输出

    char str[6];
    cin>>str; //空格字符会结束输入
    cout<<str; //遇到第一个'\0'结束。

    cin.get(str, length, endchar); //结束字符默认是'\n',结束字符会留在输入流中
    cin.getline(stxr, length, endchar); //结束字符默认是'\n',结束字符不会留在输入流中,读入的字符是length减一,因为'\0'
  5. string

    # include <cstring>
    strlen(str);//可见字符串长度,不包括'\0'

    strcpy(str1, str2); //不能用str1 = str2赋值,str1 要 大于 str2,//字符串排序
    strcat(str1, str2); //拼接
    strcmp(str1, str2); //比较大小,挨个比较ascii码 返回值是-1,0,1
    //以上三个都有n族,即strncpy,strncat,strncmp,即操作前n个字符

    strlwr(str); //转换为小写
    strupr(str);


    //应用
    len = strlen(str1);
    for(int i = 0; i < len; i++){ //不推荐
    cout << str1[i];
    }

函数

注意

  1. 声明可以写多次,定义只能写一次
  2. scanf返回值是读入的个数,ctrl Z返回-1
  3. cin返回值是truefalse

定义

  1. 定义的时候如果不声明返回值类型,默认是int

  2. 如果return类型和定义类型不同,则强转(以定义为准)

  3. 函数不可以嵌套定义,但可以嵌套调用。

传参

  1. 传入的类型不对时会发强转

变量作用域

  1. 复合语句内是局部变量
  2. 复合语句是指大括号内,不一定是循环或者函数,大括号可以随时出现,组成复合语句。

变量存储类型

每个变量都有两种属性,分别是数据类型存储类型,因此标准的变量定义应该是标准类型 数据类型 变量名

  1. auto(自动变量)函数内部或符合语句{}内。
  2. register(寄存器变量)
  3. extern(外部变量)指不在此块或此块之前声明过的变量,也可以引用其它文件的变量,另外引用其它文件的函数前面的extern可以省略
  4. static(静态(外部)变量)该变量不能由extern引用

数组作为参数

int myFun(int arr[], int n){
...
}
int myFun2(int arr[][3], int n){
...
}
int main(){
int arr1[3] = {1,2,3};
int arr2[][3] = {1,2,3,4,5,6};
myFun(arr1, 3); //注意,函数不会重新创建新的数组
myFun2(arr2, 2);
}

带默认值的函数

  1. 缺省形参值必须从右向左连续定义(自右向左入栈)
  2. 如果省掉了某个实参,直到最右边的实参都要省
  3. 缺省值应该在函数原型就给出
  4. 同一作用域,不可以重复定义缺省值
  5. 函数原型给出缺省值时,形参名可以省略
  6. 同一作用域内的函数原型和函数定义不能同时定义缺省值

内联函数

inline int fun(){};

int main(){
fun(); //本质是编译的时候将此处替换了,即变成了顺序执行,空间换取时间
}

仅在原型出加inline无效,内联函数的定义必须出现在调用之前,否则就是普通函数

如果函数体积较大或者函数内有循环比较耗时,则不宜用内联

重载函数

  1. c语言是不支持的
  2. 仅仅是返回值不同是不行的,编译不通过
  3. 编译器决定调用哪个函数的过程称之为绑定
  4. 绑定的优先级:精确->低转高->高转低
  5. 带默认值的函数等可能引起二议性

函数模板

  1. 泛型化(类型的参数化)
  2. 如果模板中有普通类型,如int,则必须显示实例化
#include <iostream>

using namespace std;

template <typename T> //也可以用class
void Swap(T& a, T& b)
{
T tmp = a;
a = b;
b = tmp;
}

void main()
{
int a = 10;
int b = 20;
Swap(a, b); //自动推到调用
//Swap<int>(a, b);//显示指定调用
cout << "a = " << a << endl;
cout << "b = " << b << endl;

float c = 12.3;
float d = 23.4;

//Swap(c, d); //自动推到调用
Swap<float>(c, d); //显示指定调用
cout << "c = " << c << endl;
cout << "d = " << d << endl;
system("pause");
}

参考资料《C++中的函数模板》

指针

定义

int a = 10;
int * p = &a;
cou<<*p; //解引用,找到内存中的数据

任何类型的指针都占四个字节

空指针和野指针

当指针定义为0、NULL、或者不赋值,此时不能解引用,否则崩溃

  1. 空指针:指向内存编号为0的指针,一般用来初始换(0-255)不可访问,系统占用。int * p = NULLint * p = 0
  2. 野指针:指向非法空间(是一种错误),无法访问。

const修饰指针

指针就是一种特殊的变量,专门用来存放地址。地址可以看作一个特殊的数据类型,地址不可以复制给int变量,但可以赋值给指针变量,int的地址,只能复制给int *。地址可以解引用,所以&a和p的用法是一样的。

常量指针

int a = 10;
const int * p = &a;
cou<<*p<<*&a<<endl;
printf("%p %p",&a, p); //地址的占位符应该用%p
a = 20; //这样是可以的
*p = 20; //不可以!!指针的指向可以修改,但不可以通过解引用来修改

指针常量

int * const p = &a; //指向不可以改,解引用可以改。

常量指针常量

const int * const p = &a; //都不可以改

指针和数组

此处,若那指针p指向数组首地址,那么此时的数组名指针名的本质其实都是一个指针,访问数组的元素可以通过方括号来访问,也可以用*来访问。需要注意的是p和a的区别,p是变量,但a是常量指针,a不可以进行a++等运算。另外,指针相加无意义,相减有意义。

int arr[3] = {1,2,3};
int * p = arr;

//利用指针遍历数组
for(int i = 0; i < 3; i++){
cout << *p << endl;
p++; //向后走四个字节,即到下个元素,p+1指向下一个元素,p-1指向上一个元素
}

//通过指针引用数组元素
//下标法 和 指针法
p[i];
a[i];
*(p+i);
*(a+i);

利用指针进行排序,可以避免复杂的例如结构体、字符串的赋值,效率更高

int main()
{
int arr[8] = {1,4,6,2,1,7,8,3};
int *p[8];
for(int i = 0; i < 8; i ++){
p[i] = &arr[i];

}
for(int i = 0; i < 7; i ++){
for(int j = i+1; j < 8; j++){
if(*p[i] > *p[j]){
int *temp = p[i];
p[i] = p[j];
p[j] = temp; //只交换指针的指向,而不更改
}
}
}
for(int i = 0; i < 8; i++){
cout<<*p[i]<<endl;
}
}

指针与字符串

指向字符串常量和指向字符数组的指针有什么区别呢?

char *string;
string = "abcd"; //string是常量区(数据段)里"abcd"的首地址,不可以修改*string的值

char *string2, ss[] = "abcd";
string2 = ss; //string2是栈里"abcd"的首地址,可以修改*string2的值

cout<<string; //即从string开始,知道'\0'结束,所以类推cout<<string+1即输出"bcd"

要搞清楚stringstring2ss三者的区别:

  1. *string不可以修改,两外两个可以
  2. ss不可以修改,两外两个可以
  3. 三者都属于指针,第一个指向常量即常量指针,第二个正常指针,第三个本身是常量即指针常量

利用指针编程的实例(复制字符串)

//把字符数组a赋值给b
int main(){
char a[] = "abcd",b[10],*p1,*p2;
p1 = a;
p2 = b;
while(*p1)
*p2++ = *p1++;
*p2 = '\0'; //不要忘了最后加上'\0'
}

指针与函数(地址传递)

主要注意传递指针以及返回指针

值传递是文件复制,地址传递是建立快捷方式

int add(int * p1, int * p2){
return(*p1 + *p2)
}

int a = 10;
int b = 20;
cout << add(&a, &b);

指向函数的指针

用的不多

int f(int a, int b){}
int (*p)(int int);
p = f;
//之后p和f用法相同,p可以用来传参

引用传递

与指针类似,但更安全、简单,主要用于函数的参数,不需要解引用,也不需要传参的时候传递地址

int a = 3;
int &b = a; //a,b地址一样,且定义的时候必须初始化,不能先定义再赋值,且以后b不能再修改

void f(int & r){
r = 5;
}

int main(){
int x = 3;
f(x);
cout<<x; //5
}

返回值为引用类型的引用

int & max(int a[], int n){
int t = 0;
for(int i = 0; i < n; i++){
if(a[i]>a[t]) t = i;
return a[t]
}
}
int & sum(int a[], int n){
int s = 0;
for(int i = 0; i < n; i++){
s += a[i];
}
return s;
}

int main(){
int a[] = {1,2,3,4,5};
int & m1 = max(a, 10); //此处m1即为a[4]
int & m2 = sum(a, 10); //此处m2即为s,但是s为局部变量,s释放之后,m2是随机值。

max(a, 10)++; //返回值是引用的话可以对返回值直接进行运算操作
}

常引用:不能通过常引用来修改变量的值,所以常引用可以用来引用常量,表达式等,通常用来作为只读形参。传引用更快,但又不希望被改动,所以更安全

int a = 1;
const int & b = a; //a,b地址相同,唯一区别是只能通过a来修改该地址的值

void f(const int & x, int & y){}
int maing(){

f(100, a); // 第一个参数可以传常量
}

动态内存

使用

先记录一个常见的错误

int main(){
int n;
cin >> n;
int a[n]; //不合法,应该使用动态数组
}

动态数组

int main(){
char *q;
q = new char[10]; //new得到的是申请到的空间的地址,当系统用完时可能会失败,当失败时会返回空指针
if(!q){ //检查new的结果
cout<<"failed"<<endl;
return 1;
}
strcpy(q, "abcde");
cout<<q<<endl;
delete []q;
return 0;
}

补充

关于内存分配的一些问题

对于三个区域,数据段、栈、堆,全局变量存储在数据段,局部栈,动态分配堆。对于一些很大的例如大数组,不能直接在堆里创建,否则会崩溃,需要在堆里new,且用完之后一定要delete否则会不断累积,造成内存泄漏,但要注意delete之后不允许再操作此处内存;也可以放在数据段里,即定义全局变量。

结构体

定义与使用

struct Student
{
string name;
int age;
}s3 //这里可以在定义的时候直接创建一个实例,不建议用
//创建后赋值
struct Student student1; //struct可以省略
student1.name = "张三";
student1.age = 10;
//创建时赋值
Student student1 = {
"张三",10
}

结构体数组

struct Student
{
string name;
int age;
};

struct Student arr[3]=
{
{"张三", 10},
{"李四", 20}
};

结构体指针

struct Student
{
string name;
int age;
};

struct Student student = {"张三", 10},


Student * p = student;
cout << p->name; //相当于(*p).name

结构体嵌套

要在之前声明

结构体传参

面向对象编程

private(成员函数可以访问本类其它对象私有成员)、publicprotected(该类以及子类)出现的次序和顺序可以任意,默认是private

类本身并不占内存

数据成员

可以使用已定义完整的类,但当前正在定义的类没有定义完整,所以不能实例化

class Grade{
int a; //不占用内存空间,不可以赋初值。新标准可以赋值,但其实是通过构造函数赋值。
Grade *p;
Grade &r;
Grade b; //错误
};

函数成员

  1. 类内定义的称为内联函数,若要在类外定义,必须在类里声明原型

    void Clock::SetTime(int h, int m, int s){ //::是作用域分辨符
    ... //访问类里变量时直接访问就可以,写法和内联一样
    }
  2. 默认形参可以放在原型里也可以放在定义处,不可都放,一般放原型

  3. 只有一份,不会给每个实例都放个函数

构造函数

  1. 没有返回值类型,且不用void的,一般函数需要void
  2. 构造函数只能被自动调用
  3. 构造函数要放在pubilc里面,否则无法实例化
  4. 构造函数可以重载
  5. 只有在不定义构造函数的时候才会自动生成无参构造函数
  6. 定义有参构造函数时最好再重载一个无参构造

对象数组

class Score{

};

int main()
{
Score ScoreArr[3]; //调用不带参数的构造函数
Score ScoreArr[3] = {{1,2,3},{2,3,4},{3,4,5}}; //带参构造函数,两种都行,初值表
Score ScoreArr[3] = {
Score(1,2,3),
Score(2,3,4),
Score(3,4,5)
}
}

常量

常量对象

const 类名 对象名;
类名 const 对象名;//两种都可以
  1. 常对象只能调用常成员函数
  2. 常对象本身以及其内部的属性等都不可以改变

常成员函数

class A{
public:
int getx() const {
...
}
int gety() const;
}

int A::gety() const{
...
}
  1. 原型和实现都要加const
  2. const可以用来重载函数
  3. 不能修改数据成员
  4. 不能调用非常成员函数
  5. 普通对象可以调用常成员函数和非常成员函数

常数据成员

定义和普通常量一样(注意:常量声明必须初始化),但是由于老标准中初始化类时不允许赋值,所以可以在构造函数里通过初始化表赋值

class A{
const int SIZE;
const int SIZE = 3; //新标准才可以如此
public:
A(int size);
}

A::A(int size):SIZE (size) //后面为参数化表可以给一个常量或者变量赋值
{...}

静态成员

静态数据成员

静态成员只保留一次拷贝

不能用构造函数初始化静态成员,必须在类外初始化

定义对象时不会为静态成员分配空间

调用时可以通过类调用也可以通过obj.调用,值相同

class A
{
static double a;
static const int b = 2;//静态常数据成员可以在此初始化(非静态常数据成员老标准不支持在此初始化)
};

double A::a = 1.3;//不要忘记初始化,初始化的时候不加static

静态成员函数

不依赖任何对象,用来访问静态数据成员,可以通过类直接调用,也可以通过对象调用。

可以在类内声明原型,然后在类外定义,此时,类外不用加static

普通函数可以访问静态变量,但是静态函数不可以直接访问普通变量,但可以访问自己创建的或是传进来的实例的变量

友元

友元类

友元函数

友元成员函数

对象析构与拷贝构造

析构函数

~构造函数名();

析构函数没有重载,没有参数,没有返回值

如果没有定义,系统会生成空析构函数

调用顺序和构造函数相反(出入栈)

拷贝构造函数

//默认拷贝构造函数,可以用旧实例来初始化新实例。
MyClass A2(A1);
MyClass A2 = A1;

在初始化,函数传参,返回值的时候会自动调用拷贝构造函数。系统默认生成拷贝构造函数。但是先声明,再赋值不会调用,而是调用=。注意一定是传变量的时候才会调用,如果直接传递常量MyClass

默认拷贝构造函数比较傻,只能浅拷贝(即直接赋值),这会导致,如果你的类用到了动态内存,那么两个指针指向会相同,所以需要自己重新定义拷贝构造函数,重新开辟内存。

而当自己重新定义拷贝构造函数之后,默认的拷贝构造函数和构造函数都会消失,所以你还需要定义构造函数。

但是如果你只是重新定义构造函数,默认的拷贝构造函数依旧完好。

运算符重载

构造函数涉及到动态内存一定要注意

  • 拷贝构造函数
  • 重新赋值运算符
  • 析构函数
  • C++ 要求’=’、’[]’、’()’、’->’运算符必须被定义为类的成员函数,把这些运算符通过全局函数进行重载时会出现编译错误;
  • 如果有一个操作数是类类型(如 string 类),那么对于对称操作符(比如操作符“==”),最好通过全局函数的方式进行重载。
  • 如果一个重载运算符是类的成员函数,那么只有当与它一起使用的左操作数是该类的对象时,该运算符才会被调用;而如果该运算符的左操作数确定为其他的类型,则运算符必须被重载为全局函数;
  • 有一些运算符是不能重载的,如“sizeof”;
  • 不能创建新的运算符;

重载为全局函数

  • 最好设置为友元函数

重载为成员函数

  • 形参少一个

常见的重载

  • =可以返回*this,这样就可以连等了!
  • []返回类型要加个&,这样就可以通过[]修改了!
  • 前置++,重置为一元,后置为二元(加个新参int x 会默认传0)
  • >> << 必须是全局

组合

如果成员类没有无参构造函数,那么组合类的构造函数的时候,必须携带初始化表。**初始化表不是在调用构造函数,构造函数的调用顺序和初始化表无关,它仅仅是提供参数。顺序应该是和数据成员里声明的顺序相同。

class A
{
class B;
public:
A(const &B1):B(B1)
{
...
}
}

继承

一些名词:继承、派生。基类、父类,派生类、子类 ,单继承,单向继承,多继承,多重继承,多层派生,多层继承

继承决定访问权限上限

派生类不继承构造函数、析构函数、赋值运算符,但是可以调用基类的

构造函数调用顺序:基类、成员对象、自己。

如果基类没有无参构造函数,那么派生类必须定义构造函数,通过参数表传递给基类,即便派生类本身不需要重新定义构造函数,此时重新定义的构造函数作用仅仅是传递参数。如果基类有的话则可以不定义。

对于多层派生,派生类会调用直接基类的构造函数,依次上溯。

继承方式如果不写,默认是private

多继承

class B:public A, public C{

}

基类构造函数调用顺序按照声明的顺序,如例子中先调用A,再C

接着调用成员对象的构造函数

最后派生类

继承默认是private

多继承要时刻注意可能出现二义性

多态

其实就是为了方便对所有的派生类进行统一管理罢了

  1. 虚函数不能是静态成员函数,也不能是友元函数,因为二者都不属于对象
  2. 多态的实现只能是指针或引用(基类指针指向派生对象,或基类引用指向派生对象)
  3. 派生类继承基类的虚函数,无论写不写virtual都是虚函数
  4. 派生类的重载函数会覆盖继承过来的同名虚函数

虚析构函数

当派生类需要析构去delete动态内存时,如果是基类的指针,只会执行基类的析构函数,为了能够析构派生类,所以加了virtual。同时派生类会调用基类的析构函数。而基类不会调用派生类的析构函数。

纯虚函数

只有原型没有实体

virtual int f(int, double) = 0;

抽象类

一个类中至少有一个纯虚函数,则称之为抽象类。这种类只能作为基类,不能创建对象,但可以创建指针和引用。

STL

string

#include <string>
string s1; //空串
char *str1 = "hhh";
char str2[] = "hhh";

//构造函数
string s1(str1);
string s1(str2);
string s1("hhh");
string s1(str1, 3); //前几个字符
string s2(s1); //拷贝构造
string s2(s1, 2, 3); //从2,拷贝3个。
string s2(s1, 2); //从2,拷贝到结束
string s2(3, 'c'); ///ccc

//输入
cin>>s1; //开头空格不算,中间空格结束
getline(cin, s1, c); //输入流、string、结束符(默认回车),且结束符会被丢弃。如果第一个就是结束符,那么就是空串,如果之前又输入字符,需要getchar()或者cin.get()吃掉回车。返回值是输入流


//遍历
s1[i]; //下标,注意没有'\0'
for(char ch:s);//范围循环
for(auto &ch:s);//类型可以自动,&可以修改源字符串,否则是副本
//迭代器iterator reverse_itrerator const_iterator,对于常量,必须用第三个
for(string::iterator it=s.begin(); it<s.end(); it++)
cout<<*it<<endl;

//运算符重载
+, =, +=, ==, !=, >, >=....

//方法(不写那么细致了)
append();
push_back();
insert();
erase();
clear();
replace();
size();
length();
empty();
compare();//可以截取范围
assign();//赋值
substr();//子串
swap();//交换
c_str();//转换为c字符数粗

输入输出

基于控制台的I/O

​ cin cout

基于字符串的I/O

  1. istringstream:流的输入

  2. ostringstream:流的输出

  3. stringstream:输入输出

  4. string str = "asdkfjasdf";
    stringstream ss(str);//创建字符流对象
    ss>>a>>b>>s;//即从ss对象输入其它变量。
    ss<<"234"<<"2"<<endl;//输入到字符串
    string s2 = ss.str();//转化为字符串
    
    //可以用来做不同类型数据的转换
    template<typename out_type, typename in_type>
    out_type convert(const in_type &t)
    {
        stringstream stream;
        steam<<t;
        out_type res;
        stream>>res;
        return res;
    }
    <!--code42-->
    
//操作样例,从文件输出
int main()
{
char name[8],score[6];
ifstream txtfile;
txtfile.open("d:\\xxx.txt");
if(!txtfile)
{
cerr<<"error"<<endl; //cerr无缓冲输出,迅速的很呐!
exit(1);
}
if(!txtfile.eof()) //判断是否读完了!只不过这样会重复输出最后一行,所以在下边加个if!
{
if(txtfile>>name>>score)//防止最后一行重复
cout<<name<<' '<<score<<endl;
}
txtfile.close();
}

//读取二进制文件
int main()
{
CStudent s;
ifstream inFile("students.dat",ios::in|ios::binary); //二进制读方式打开
if(!inFile) {
cout << "error" <<endl;
return 0;
}
while(inFile.read((char *)&s, sizeof(s))) { //一直读到文件结束,可以用binfile.peek()!=EOF来判断
int readedBytes = inFile.gcount(); //看刚才读了多少字节
cout << s.szName << " " << s.age << endl;
}
inFile.close();
return 0;
}

分文件编写

  1. h写声明,.cpp写定义,最后新的cpp里引用.h即可

杂乱

头文件

踩坑

  1. pow是浮点计算,貌似算出来的数可能导致不相等,可以加个(int),加(int)会导致不准确,需要自己写函数(不同编译器不一样效果)

  2. cout输出小数不会带后面的0;

  3. 当在循环的时候要找到最好的判断方式,在最合适的地方break,不然很容易超时!

  4. cin>>char1不会读入空格,scanf可以

  5. 第一个cin.getline之前要放一个getchar

    int main()
    {
    int n;
    cin>>n;
    getchar();
    for(int i = 0; i < n; i++){

    int sum = 0;
    char str[60];
    cin.getline(str, 60);
    int len = strlen(str);
    for(int j = 0; j < len-1; j++){
    if(str[j] == ' ' && str[j+1] != ' ') sum++;
    }
    if(str[0] == ' ')
    {
    sum--;
    }

    cout<<sum+1 <<endl;
    }
    }

  1. 如果定义了拷贝构造函数,记得要把其它属性赋值,不然你传参的时候就错了!!!

  2. 析构貌似不用delete[];

考试复习

第一次课

  1. ‘\xCC’。\x是表示16进制,即CC是十六进制。
  2. -=返回值是改变后的左侧的数
  3. Size of char : 1
    Size of int : 4
    Size of short int : 2
    Size of long int(long) : 8
    Size of float : 4
    Size of double : 8
    Size of wchar_t : 4
  4. 1.0小数默认是double,如果是1.0f则是float
  5. ;可以是一句话
  6. ‘0’——48,‘A’——65,’a’——97;
  7. 取余%必须是整型

第二次课

  1. 注意if后面不加{}的话,只能读一句。

  2. int main()
    {
       int a = 1, b = 2, c = 3;
       if(a < b)
          if(b > c)
                cout<<3;
       else
          cout<<4; //最终输出4,不加括号时,else只能跟最近的if
    }
    <!--code45-->
  3. 函数原型可以只声明变量类型,而不声明变量名称,且不需要{}

  4. 函数都要通过main来调用,main是入口,所以函数不能单独运行,但是可以单独编译

第八次课

  1. 对于double a[3][5]a[1][5]是不对的!
  2. char a[3] = {'a','b','c'}不可以用strlen(),因为没有结束符’\0’。
  3. 对于c_string的字符数组,注意最后的结束符,另外\\是一个字符。

第九次课

  1. 不可以用1,’a’这样的常量给指针赋值
  2. int a[] = {1,2,3}a是不可以变的!但是如果是形参,是可以变的!

第十一次课

  1. 函数模板显示实例化与隐式实例化的条件,如果有普通类型,如int,则必须显示

第十二次课

typedef struct ST
{
long a;
int b;
char c[2];
}NEW; // 给结构体起了别名,如果没有typedef的话,NEW在此处表示一个结构体

ST st[] = {{1,2,'a'},{2,3,'b'}};
cout<<(&st[0])->a; //必须加括号,不然编译出错。

第十三次课

  1. 常成员函数不可以修改属性值,但可以访问。常成员函数不可以调用非常成员函数。

  2. 常成员函数可以访问类中的所有数据成员,但不能修改。注意常数据成员要被初始化,(可以在构造函数初始化0

  3. 静态函数可以访问静态变量,但不能访问其它变量。普通函数可以访问静态变量。

  4. 注意静态数据成员的初始化

  5. 普通成员函数不能:x(a),y(b)

  6. 常对象只能调用常成员函数

  7. 拷贝构造函数的参数const point &p

  8. 友元函数可以把原型和定义都写在类里,但是即便写在类里,也不是成员函数。friend只能用在类里。

  9. 当涉及到友元成员函数的时候,因为会涉及到相互依赖的问题,所以只写函数原型,函数定义要放在后面。

  10. %,必须是int

  11. switch注意后面是否有break!

第十四次课

  1. 是double后面要有个小数点么
  2. 函数默认返回值是int
  3. 赋值表达式t=1的值是t