大学c++复习谭浩强《C++程序设计》第三版

c++复习 ,教材谭浩强《C++程序设计》第三版(以防你们需要这本书的电子版,特意上传到了蓝奏云),尽管这本书有些小错误,但是谭浩强讲的确实很通俗易懂。因为我是自学,虽然已经买了郑莉的书,但是谭浩强的更易懂。下面是我照着抄的代码,作为记录,方便自己复习。

 

第九章 怎样使用类和对象

构造函数

大学c++复习谭浩强《C++程序设计》第三版_第1张图片

#include
using namespace std;
class box {
	int l, w, h;
public:
	box() {
		l = 10;
		w = 10;
		h = 10;
	}
	int volume() {
		return l * w * h;
	}
};

int main() {
	box box1;//一定不能带括号
	cout << box1.volume() << endl;
}

总之,如果对象没有带参数,就不要带括号!!!如果带了括号,会被认为声明一个返回值类型为box的函数。

 

 

大学c++复习谭浩强《C++程序设计》第三版_第2张图片

总之,一个类可以不用参数调用的构造函数只能有一个,不然会出现二义性。

析构函数

大学c++复习谭浩强《C++程序设计》第三版_第3张图片

大学c++复习谭浩强《C++程序设计》第三版_第4张图片

 各类指针

1.函数指针

调用函数的通常形式“函数名(参数表)”的实质就是“函数代码首地址(参数值)”。函数指针就是专门用于存放函数代码首地址的变量,也就是一旦函数指针指向某个函数,它与函数名的作用完全一样。 声明函数指针时,需要说明函数的返回值,参数列表。

语法形式:数据类型 (*函数指针名)(参数列表)     int(*m)(int, int); //声明函数指针,记得加括号,不然就变成了声明返回值为int指针的函数

赋值语法形式:函数指针名=函数名   m = &max;  //&可省略

调用形式:(*m)(1,2);或者m(1,2);

2.对象指针:就是用于存放对象地址的指针的变量。

声明形式:类名 *对象指针名;

赋值形式:对象指针名=&对象名;   time* pt=&t;

访问对象成员:(*对象指针名).对象成员;或对象指针名->对象成员;    pt->display();   (*pt).display();

3.指向类成员的指针

1.指向对象非静态数据成员的指针
 声明形式:数据类型 *指针名;  int* s = &t.second;
 赋值形式:指针名=&对象名.数据成员名 (数据是公有才能被访问)

2.指向类静态数据成员的指针
 声明形式:数据类型 *指针名; 
 赋值形式:指针名=&类名::数据成员名(数据是公有才能被访问)  int *c = &time::count;
 int* c2 = &t.count;/也可以和非静态数据成员一样通过对象调用

 3.指向类成员函数的指针
  声明形式:数据类型 (类名::指针名)(参数列表);
  赋值形式:指针名=&类名::成员函数名 (&可以省去)
  void (time::* d)() = &time::display;  //括号不能省掉

#include
using namespace std;

class time {
public:
	time(int h, int m, int s) :hour(h), minute(m), second(s) {
		count++;
	}
	void display() {
		cout << hour << ":" << minute << ":" << second << endl;
	}
	int second;
	static int count;
private:
	int hour, minute;
};
int time::count = 0;
int max(int a,int b) {
	return a > b ? a : b;
}

int main() {

	//1.调用函数的通常形式“函数名(参数表)”的实质就是“函数代码首地址(参数值)”
	//函数指针就是专门用于存放函数代码首地址的变量,也就是一旦函数指针指向某个函数,它与函数名的作用完全一样
	//声明函数指针时,需要说明函数的返回值,参数列表。
	//语法形式:数据类型 (*函数指针名)(参数列表) 赋值语法形式:函数指针名=函数名
	int(*m)(int, int); //声明函数指针,记得加括号,不然就变成了声明返回值为int指针的函数
	m = &max;  //&可省略
	cout << m(1, 2) << endl;
	//2.对象指针:就是用于存放对象地址的指针的变量。
	//声明形式:类名 *对象指针名; 赋值形式:对象指针名=&对象名; 访问对象成员:(*对象指针名).对象成员;或对象指针名->对象成员;
	time t(1,2,3);
	time* pt=&t;
	pt->display();
	(*pt).display();
	//3.1指向对象非静态数据成员的指针
	//声明形式:数据类型 *指针名; 
	//赋值形式:指针名=&对象名.数据成员名 (数据是公有才能被访问)
	int* s = &t.second;
	cout << *s << endl;
	//3.2指向对象静态数据成员的指针
	//声明形式:数据类型 *指针名; 
	//赋值形式:指针名=&类名::数据成员名(数据是公有才能被访问)
	int *c = &time::count;
	int* c2 = &t.count;
	cout << *c<

共用数据的保护

1.常对象

定义形式:类名 const 对象名[(实参表)];或者const 类名 对象名[(实参表)]; 定义常对象,必须同时对其初始化,之后不能再改变。常对象只能调用常成员函数

2.常数据成员

只能通过构造函数的初始化列表对常数据成员进行初始化,任何其他函数都不能对常数据成员赋值。

3.常成员函数

声明形式:类型 函数名(参数表) const。在声明和定义常成员函数时一定要加const,但调用时可以不加。常成员函数只能引用本类数据成员,而不能修改。

友元

#include
using namespace std;
//提前引用声明
class date;
class time {
public:
	time(int, int, int);
	void display(date &d);

private:
	int hour, minute, second;
};
time::time(int a, int b, int c) :hour(a), minute(b), second(c) {

}
class date {
public:
	date(int y,int m,int d):year(y),month(m),day(d) {

	}
	//需要声明类time的display为友元函数,而不是仅仅声明display为友元函数
	friend void time::display(date& d);
private:
	int year, month, day;

};

void time::display(date& d) {
	cout << d.year<<"/"<

 当声明成员函数为友元函数时候,要记得加类名修饰。

类模板

#include
using namespace std;

template 
class compare {
private:
	T a, b;
public:
	//构造函数
	compare(T a, T b) :a(a), b(b) {
	}
	T max();
	T min();
};
//如果将成员函数写在类外,需要附带template 
//而且类名后面还得加类型
template
T compare::min() {
	return a < b ? a : b;
}


template
T compare::max() {
	return a > b ? a : b;
}


int main() {
	//需要在类模板名后面用尖括号指定实际的类型名
	compare a(4, 5);
	cout << a.min() << endl;
	compare m(2.2, 8343.0);
	cout << m.min() << endl;

	comparec(0, 10);
	cout << c.max();
	return 0;
}

 总之,就是一定要记得声明对象时用尖括号说明实际类型,还有函数体放在类外的时候要加template; 而且同声明对象一样,也要在类名后面加尖括号说明虚拟类型。

 大学c++复习谭浩强《C++程序设计》第三版_第5张图片

第十章运算符重载

运算符重载为成员函数

#include
using namespace std;

class complex {
	double real, image;

public:
	complex() {
		real = 0;
		image = 0;
	}
	complex(double real,double image): real(real),image(image){

	}
	complex operator+ (complex& c2) {
		return complex( real+c2.real,image+c2.image); //创建临时无名对象
	}
	complex operator-(complex&);
	void display();
};
complex complex::operator -(complex& c2) {
	return complex(real - c2.real, image - c2.image);
}
void complex::display() {
	cout << "(" << real << "," << image << "i)" << endl;
}

int main() {
	complex c1(5, 6),c2(1,1),c3;
	cout << "c1="; c1.display();
	cout << "c2="; c2.display();
	c3 = c1 + c2;
	cout << "c3=c1+c2="; c3.display();

}

第十一章派生类

其中很重要的就是三种继承方式:public、private、protected。

派生类的构造函数和析构函数

派生类构造函数的一般形式:派生类构造函数名(总参数表):基类构造函数名(参数表){派生类新增数据成员的初始化语句 }

在执行派生类的构造函数时,会调用基类的构造函数。

#include
#include
using namespace std;

class student {

public:
	//定义基类构造函数
	student(int num,string name):num(num),name(name) {

	}
protected:
	int num;
	string name;
};
//声明公有继承
class student1 :public student {
	int age;
	char gender;
public:
	//定义派生类的构造函数
	student1(int num, string name, int age, char gender) :student(num,name),age(age),gender(gender){

	}
	void display() {
		cout << "num:" << num << endl;
		cout << "name:" << name << endl;
		cout << "age:" << age << endl;
		cout << "gender:" << gender << endl;
	}
};



int main() {
	student1 s1(101,"liu",22,'F');
	s1.display();
	return 0;
}

在定义派生类的构造函数时,同时也要给基类的构造函数初始化,注意,这里只是调用基类的构造函数,而不是定义基类的构造函数。

如果在类外定义派生类的构造函数,在类中对构造函数进行原型声明时,不用写“基类构造函数名(参数表)”,只有在定义函数的时候才将它列出。

class student1 :public student {
	int age;
	char gender;
public:
	//声明派生类的构造函数
	student1(int num, string name, int age, char gender);
	void display() {
		cout << "num:" << num << endl;
		cout << "name:" << name << endl;
		cout << "age:" << age << endl;
		cout << "gender:" << gender << endl;
	}
};

//在类外定义构造函数
student1::student1(int num, string name, int age, char gender) :student(num, name), age(age), gender(gender) {

}

多层级派生时的构造函数

一个类不仅可以派生出一个派生类,派生类还可以继续派生。在写构造函数数时,派生类只需要初始化直接基类的构造函数,无须列出每一级间接基类。

#include
#include
using namespace std;
//声明间接基类
class student {
public:
	//定义基类构造函数
	student(int num,string name):num(num),name(name) {
	}
protected:
	int num;
	string name;
};
//声明直接基类
class student1 :public student {
	int age;
public:
	//声明派生类的构造函数,只需要写直接基类的参数表即可。
	student1(int num, string name, int age) :student(num, name), age(age) {

	};
	void display1() {
		cout << "num:" << num << endl;
		cout << "name:" << name << endl;
		cout << "age:" << age << endl;
	}
};
//声明派生类
class student2 :public student1 {
	char gender;
public:
	student2(int num,string name,int age,char gender):student1(num,name,age),gender(gender) {
	}
	void display2() {
		display1();
		cout << "gender:" << gender << endl;
	}
};
int main() {
	student2 s2(101,"liu",22,'F');
	s2.display2();
	return 0;
}

派生类的析构函数

派生类是不能继承基类的析构函数的,也需要通派生类的析构函数去调用基类的析构函数。析构函数的调用顺序与构造函数正好相反:先执行派生类自己的析构函数,对派生类新增加的成员进行清理,然后调用子对象的析构函数,对子对象进行清理,最后调用基类的析构函数,对基类进行清理。

多重继承引起的二义性问题

大学c++复习谭浩强《C++程序设计》第三版_第6张图片

大学c++复习谭浩强《C++程序设计》第三版_第7张图片

int main{
    C c1;
    c1.A::a=3; //需要用指明c1的调用的是哪一个直接基类的成员
    c1.A::display(); //需要用指明c1的调用的是哪一个直接基类的成员
}

 

大学c++复习谭浩强《C++程序设计》第三版_第8张图片

虚基类

注意:虚基类并不是在声明基类时声明的,而是在声明派生类时,指定继承方式时声明的。 声明虚基类的方式:

class 派生类名:virtual 继承方式 基类名;

大学c++复习谭浩强《C++程序设计》第三版_第9张图片

大学c++复习谭浩强《C++程序设计》第三版_第10张图片

在最后的派生类中,不仅要对其直接基类进行初始化,还要虚基类进行初始化。C++编译系统只执行对最后的派生类对虚基函数的调用,而忽略掉虚基类的其他派生类(如类类C、类B),这就保证了虚基类的数据成员不会被多次初始化。

#include
#include
using namespace std;
//声明公共基类
class person {
protected:
	string name;
	char sex;
	int age;
public:
	person(string name,char sex,int age):name(name),sex(sex),age(age){}
};
//person类的直接派生类,声明继承虚基类
class teacher :virtual public person {
public:
	//构造函数
	teacher(string name, char sex, int age,string title) :person(name, sex, age), title(title) {
	}
protected:
	string title;
};
//person类的直接派生类,用virtual声明person为虚基类
class student :virtual public person {
public:
	student(string name, char sex, int age, float score) :person(name, sex, age), score(score) {
	}
protected:
	float score;
};
//声明多重继承graduate类
class graduate :public student, public teacher {
	//要给直接基类初始化,还要给间接基类初始化
public:
	graduate(string name, char sex, int age,string title,float score,float wage):person(name,sex,age),teacher(name,sex,age,title),student(name,sex,age,score),wage(wage) {
	}
	void display() {
		cout << "name:" << name << endl;
		cout << "sex:" << sex << endl;
		cout << "age:" << age << endl;
		cout << "title:" << title << endl;
		cout << "score:" << score << endl;
		cout << "wage:" << wage << endl;
	}
protected:
	float wage;
};
int main() {
	graduate g1("wang", 'f', 22, "assistant", 90, 10000);
	g1.display();
}

累死我了,在给graduate写初始化列表时,真的太长一串了。虚基类牛逼,要给所有的基类初始化。

基类与派生类的转换

大学c++复习谭浩强《C++程序设计》第三版_第11张图片

注意:只能用子类的对象给其基类对象进行赋值,而不能用基类的对象对其子类对象进行赋值。 

大学c++复习谭浩强《C++程序设计》第三版_第12张图片

大学c++复习谭浩强《C++程序设计》第三版_第13张图片 

第十二章 多态性与虚函数

大学c++复习谭浩强《C++程序设计》第三版_第14张图片 

 

你可能感兴趣的:(C++,c++)