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

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

 

第九章 怎样使用类和对象

构造函数

#include<iostream>
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的函数。

 

 

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

析构函数

 各类指针

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<iostream>
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<<endl; //也可以和非静态数据成员一样通过对象调用
	//3.3指向对象成员函数的指针
	// 声明形式:数据类型 (类名::指针名)(参数列表);
	//赋值形式:指针名=&类名::成员函数名 (&可以省去)
	void (time::* d)() = &time::display;//括号不能省掉
	
}

共用数据的保护

1.常对象

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

2.常数据成员

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

3.常成员函数

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

友元

#include<iostream>
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<<"/"<<d.month<<"/"<<d.day<<"\t";
	cout << hour << ":" << minute << ":" << second << endl;

}

int main() {
	time t(13, 41, 56);
	date d(2020, 11, 28);
	t.display(d);

}

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

类模板

#include<iostream>
using namespace std;

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


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


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

	compare<bool>c(0, 10);
	cout << c.max();
	return 0;
}

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

 

第十章运算符重载

运算符重载为成员函数

#include<iostream>
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<string>
#include<iostream>
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<string>
#include<iostream>
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;
}

派生类的析构函数

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

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

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

 

虚基类

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

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

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

#include<string>
#include<iostream>
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写初始化列表时,真的太长一串了。虚基类牛逼,要给所有的基类初始化。

基类与派生类的转换

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

 

第十二章 多态性与虚函数

 

 

  • 24
    点赞
  • 77
    收藏
    觉得还不错? 一键收藏
  • 3
    评论
C++程序设计 扫描版,谭浩强编著,清华大学出版社,2004年6月第一版。 注意:其他两卷在本网页下面我的其它资源里可以找到 内容简介 C++是近年来国内外广泛使用的现代计算机语言,它既支持面向过程的程序设计,也支持基于对象和面问对象的程序设计。国内许多高校已陆续开设了C++程序设计课程。但是由于C++涉及概念很多,语法比较复杂,内容十分广泛使不少人感到学习难度较大,难以人门。 本书作者深入调查了我国大学程序设计课程的现状和发展趋势参阅了国内外数十种有关C++教材,认真分析了学习者在学习过程中遇到的困难,研究了初学者的认识规律。在本书中做到准确定位,合理取舍内容,设计了读者易于学习的教材体系,并且以通俗易懂的语言化解了许多复杂的概念,大大减少了初学者学习C++的困难。 考虑到许多读者在学习C++前未学过其他语言本书把入门起点降低,读者不需要具备C语言的基础。本书包括14章,分为4 篇:基本知识面向过程的程序设计;基于对象的程序设计面向对象程序设计。本书内容全面,例题丰富,概念清晰,循序渐进,易于学习。 本书是依据ANSI C++标准进行介绍的,引导读者从开始就按标准C++的规定编程。本书配有两本辅导教材,即《C++程序设计题解与上机指导》 和《C++编程实践指导》。 本书是大学各专业学生学习C++的基础教材,也是适于初学者学习的教材。即使没有教师讲授,读者也能看懂本书的大都分内容
评论 3
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值