LaoTanCpp

谭浩强版C++速览

6.5 函数与指针

指针变量也可以指向一个函数.一个函数在编译时被分配给一个入口地址.这个函数入口地址就被称为函数的指针.

1
2


6.6 返回指针值的函数

就是返回地址的函数.简称指针函数

int *a(int x,int y);

6.7 指针数组和指向指针的指针

6.7.1 指针数组

int *p[4];

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
int main()
{
void sort(char *name[],int n);
void print(char *name[],int n);
char *name[] = {"BASIC","FORTRAN","C++","Pascal","COBOL"};
int n =5;
sort(name,n);
print(name,n);
return 0;
}
void sort(char *name[],int n)
{
char *temp;
int i,j,k;
for(i=0;i<n-1;i++)
{
k=i;
for(j=i+1;j<n;j++)
if(strcmp(name[k],name[j])>0)
k=j;
if(k!=i)
{
temp=name[i];
name[i]=name[k];
name[k]=temp;
}
}
}
void print(char *name[],int n)
{
int i;
for(i=0;i<n;i++)
{
cout<<name[i]<<endl;
}
}

6.7.2 指向指针的指针

char **p;

1
2
3
4
5
6
char **p;
char *name[]={"BASIC","FORTRAN","C++","Pascal","COBOL"};
p = name + 2;
cout<<*p<<endl;
cout<<**p<<endl;
return 0;

6.8 const指针

  1. 指向常量的指针变量 const int *p=&a;
  2. 常指针 char * const p1 =”China”;
  3. 指向常量的常指针 const int * const pt =&a;

6.9 void指针

void *,不指向任何类型的数据.

即不指向确定类型的数据.

1
2
3
4
5
6
7
8
9
int a = 3;
int *p1 = &a;
char *p2 = "new";
void *p3;
p3 = (void *)p1;
cout << *(int*)p3 << endl;
p2 = (char *)p3;
printf("%d", *p2);
return 0;

可以把非void 型的指针赋值给void型指针变量.

6.10 指针小结

  1. 指针加减p++
  2. 指针赋值 p=&a; p=array; p=&array[i]; p = max; p1=p2;
  3. 指针变量可以有空值 p=NULL;
  4. 两个指针变量可以相减; 相加没有实际意义
  5. 指针赋值需要注意类型问题;

6.11 Reference

6.11.1 变量的引用

int a;

int &b = a;//声明b是a的引用.

在数据类型名后面出现的&是引用声明符,在其他场合出现的都是地址符.

效果类似 ref in c#

结构体

7.1.5 指向结构体变量的指针

1
2
3
4
Student stu;
Student *p = &stu;
cout << stu.num << " " << stu.name << " " << stu.sex << " " << stu.score << endl;
cout << p->num << " " << (*p).name << " " << (*p).sex << " " << (*p).score << endl;

7.4 简单链表

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
struct student
{
int num;
float score;
struct student *next;
};
int main()
{
student a,b,c,*head,*p;
a.num =31001;a.score=89.5;
b.num =31003;b.score=90;
c.num =31007;c.score=85;
head = &a;
a.next = &b;
b.next = &c;
c.next = NULL;
p=head;
do
{
cout<<p->num<<" "<<p->score<<endl;
p = p->next;
}while(p!= NULL);
return 0;
}

7.1.6 结构体类型数据作为函数参数

2->用指向结构体变量的指针作为实参

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
struct Student
{
int num;
string name;
float score[3];
}stu = {12345,"Li Ning",67.5,89,98};
int main()
{
void print(Student *);
Student *pt = &stu;
print(pt);
return 0;
}
void print(Student *p)
{
cout<<p->name<<" "<<p->name<<" "<<p->score[0]<<" "
<<p->score[1]<<" "<<p->score[2]<<endl;
}

3->用变量的引用作为函数参数

1
2
3
4
5
6
7
8
9
10
int main()
{
void print(Student &);
print(stu);
return 0;
}
void print(Student &stud)
{
cout<<stud.num<<endl<<stud.name<<stud.score[0]<<stud.score[1]<<stud.score[2]<<endl;
}

7.2 枚举类型

1
2
3
4
5
6
7
8
9
enum color
{
red,
yellow,
blue,
white,
black
};
cout<<color(1)<<color(2)<<endl;

7.3 typedef声明新的类型名

  1. typedef int NUM[100]; NUM n;
  2. typedef char* STRING; STRING p,s[10];
  3. typedef int(*POINTER)() POINTER p1,p2;

8 类和对象的特性

8.1 面向对象程序设计方法概述

面向对象程序设计有4个主要特点:抽象\封装\继承和多态

与基于过程做比较,往往把基于对象程序设计和面向对象程序设计统称为面向对象程序设计.

8.1.1 什么是面向对象的程序设计

  1. 对象: 客观世界中任何一个事物都可以看作一个对象.任何一个对象都具有两个要素,即属性和行为.对象是由一组属性和一组行为构成的. 在一个系统的多个对象之间通过一定的渠道相互联系.要使某一个对象实现某一种行为,应当向它传送相应的消息.
  2. 封装与信息隐蔽:可以对一个对象进行封装处理,把它的一部分属性和功能对外界屏蔽.即为封装.封装性:1是将有关的数据和代码封装在一个对象中,形成一个基本单位,各个对象之间相对独立,互不干扰.2是将对象中某些部分对外隐蔽,即隐蔽其内部细节,只留下少量接口,以便与外界联系,接收外界的消息.
  3. 抽象: 抽象的作用是表示同一类事物的本质.归纳为类?类是对象的抽象,而对象是类的特例,即类的具体表现形式.
  4. 继承与重用:站在巨人的肩膀上,用别人的攻略打自己的心魔.
  5. 多态性:polymorphism 由继承而产生的不同的派生类,其对象对同一消息会做出不同的响应.

8.1.3 类和对象的作用

一组数据是与一组操作相互对应的.因此人们把相关的数据和操作放在一起.形成一个整体,与外界相对分隔.这就是面向对象的程序设计中的对象.

程序 = 对象s+消息

8.2 类的声明和对象的定义

8.2.2 类的声明

1
2
3
4
5
class 类名
{
private:
public:
};
1
2
3
4
5
6
7
8
9
10
11
12
class Student
{
private:
int num;
char name[20];
char sex;
public:
void display()
{
cout<<"Num:"<<endl;
}
};

8.3 类的成员函数

1
2
3
4
5
6
7
8
9
10
11
12
13
class Student
{
public:
void display();
private:
int num;
string name;
char sex;
};
void Student::display()
{
cout<<"Hello world"<<endl;
}

::作用域限定符

8.3.3 内置成员函数

inline void Student::display(){};

8.4.2 通过指向对象的指针访问对象中的成员

1
2
3
4
5
6
7
8
9
class Time
{
public:
int hour;
int minute;
}
Time t,*p;
p=&t;
cout<<p->hour;

8.5 类的封装性和信息隐蔽

8.6 类和对象的简单应用

class Time
{
public:
Time()
{
hour = 0;
minute = 0;
sec = 0;
}
void set_time();
void show_time();
private:
int hour;
int minute;
int sec;
};

9 怎么使用类和对象

9.1.2 构造函数

无参构造

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
class Time
{
public:
Time()
{
hour = 0;
minute = 0;
sec = 0;
}
void set_time();
void show_time();
private:
int hour;
int minute;
int sec;
};

含参构造

从外部传参设定初始

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
class Box
{
public :
Box(int, int, int);
int volume();
private:
int height;
int width;
int length;
};
Box::Box(int h, int w, int len)
{
height = h;
width = w;
length = len;
}

9.1.4 用参数初始化表对数据成员初始化

Box::Box(int h,int w,int len):height(h),width(w),length(len)

9.1.5 构造函数的重载

9.2 析构函数

9.5.2 指向对象成员的指针

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
class Time
{
public:
Time(int, int, int);
int hour;
int minute;
int sec;
void get_time();
};
Time::Time(int h, int m, int s)
{
hour = h;
minute = m;
sec = s;
}
void Time::get_time()
{
cout << hour << ":" << minute << ":" << sec << endl;
}
int main()
{
Time t1(10, 13, 56);
int *p1 = &t1.hour;
cout << *p1 << endl;
t1.get_time();
Time *p2 = &t1;
p2->get_time();
void(Time::*p3)();
p3 = &Time::get_time;
(t1.*p3)();
return 0;
}

9.10.1 友元函数

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
class Time
{
public:
Time(int, int, int);
//friend void display(Time &);
private:
int hour;
int minute;
int sec;
};
Time::Time(int h, int m, int s)
{
hour = h;
minute = m;
sec = s;
}
void display(Time &t)
{
cout << t.hour << ":" << t.minute << ":" << t.sec << endl;
}
int main()
{
Time t1(10, 13, 56);
display(t1);
return 0;
}

9.10.2 友元类

如将Time类声明为Date类的友元类,Time中所有函数都可以访问Date类中的所有成员.

使用友元会破坏封装,谨慎使用.

9.11 类模板

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
template <class numtype>
class Compare
{
public:
Compare(numtype a, numtype b)
{
x = a; y = b;
}
numtype max()
{
return(x > y) ? x : y;
}
numtype min()
{
return(x < y) ? x : y;
}
private:
numtype x, y;
};
int main()
{
Compare<int> cmpl(3, 7);
cout << cmpl.max() << endl;
cout << cmpl.min() << endl;
Compare<float> cmp2(45.78, 93.6);
cout << cmp2.max() << endl;
cout << cmp2.min() << endl;
return 0;
}

10 运算符重载

10.9.2 转换构造函数

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
class Complex
{
public:
Complex() { real = 0; imag = 0; }
Complex(double r, double i) { real = r; imag = i; }
operator double() { return real; }
private:
double real;
double imag;
};
int main()
{
Complex c1(3, 4), c2(5, 10), c3;
double d;
d = 2.5 + c1;
cout << d << endl;
return 0;
}