关于我大一第一个学期学习的C++

121 阅读6分钟

真正的步入大学以后,学到的第一门语言是C++,正好最近有一个活动,趁着期末,写一下这个学期对C ++的总结和感受(想要混综测)

第一章:绪论

深刻的记着我听这一章什么也没有懂,都是在网上查资料啥的(作为一个只会开关机的green hand),最后只是简单了解到了面向对象的一些特点,还有一些进制之间的转换计算,还有原码,补码,反码啥的

第二章:C++语言简单程序设计

开头先学习了C++的大体结构:预处理指令#include<iostream,命名空间using namespace std;主函数main

现在还有一个没有弄明白的东西:cpp扩展名,称为C++的源文件,还有如何写多个文件来运行一个程序,在考完试重点弄一下,先着重于考试

关键字:

在程序中有特定的含义,引出了标识符的定义规则:只能以大写字母,小写字母,下划线(_)开始,在组成方面,可以有大写字母,小写字母,数字和下划线组成,所以说在开头不能以数字开头

基本数据类型:

在这里主要学习了各种类型的长度等,比较重要的:char(1),int(4),float(4),double(8),还有后面老师提到的指针类型是8,然后就是unsigned当时没有太理解,sign是表示有符号数,unsigned的是无符号数,有符号数的最高位数0,1表示的是这个数字的正负,其余位表示数据,对于无符号数unsigned来说,所有位都表示数据

常量:

重点想记录一下字符常量(因为给的题里估计期末会考一点),字符是用单引号括起来的,其中转义字符,如'\n'表示换行 '''表示单引号, 然后 '"'表示双引号 。 '\'表示字符\ 但是在用的时候要加上单引号才能有效果(小插曲:第一次写程序的时候,用char类型的时候一直用的双引号,导致程序一直运行不起来,一直在生气为什么运行不了,也不知道单引号怎么打,直到我的高中同学和我说可能符号错了,我人生中第一次学会了输出电脑上的单引号)

字符串常量:

在形式上,是用双引号,在储存形式上,与字符常量不同的是字符串常量会在末尾添加'\0'作为标记,比如"a"====a \0 ------> 'a'====a

布尔变量:

占一字节,真或假,0假1真,或者其他不是1和0的都代表真,在数据类型转换有相关理解

运算符与表达式:

算数运算符:

%是取余运算符,只能用于整型操作数(两个小数不能取余),有一个也是关于除法的/,用于两个整数相除时,仅取结果商的整数部分,小数部分被自动舍弃,但是如果是两个小数相除,结果还是小数,还有自增自减,前置后置两种,具体的放上代码当时研究了一晚上才明白,高兴的是后来老师提问我也都会了,下面是我当时连着条件运算一起弄懂的代码:

int main(){

int a, b, c, d, e, f;
int x = 10, y = 9;
int l = 10, k = 9;
a = (--x == y++) ? x-- : ++y;
cout << "a  " << a << endl;//9
cout << "x  "<<x << endl << "y  "<<y << endl;//8,10
b = x++;//8
cout << "x  " << x << endl;//9
e = (l-- == k++) ? l-- : ++k;
cout << "e  " << e << endl;//11
cout << "l  " << l << endl;//9
cout << "k  " << k << endl;//11

}

接下来是赋值运算:

其实这里我不太明白的是一些赋值时的形式,比如:x*=y+8 ---(x=x*(y+8))还有一个 a+=a-=aa----(a=a+(a=a-aa))......反正就是好多不太会的不太理解的形式

这里还有一个逗号运算:

a=35,a4 最终结果是60,解答顺序是先解一,再解二,最终答案为二的值

逻辑运算:

第一个比较容易忽视的是关系运算符的优先级问题,先说知识点: 关系表达式的结果只能是bool类型的,结果是ture 或者false,比如:a>b,c<=a+b,x+y==3等都算是关系表达式,并且在这里的==不要和赋值运算符=弄混

然后是关于!(非),是指反向取值,&&(与),||(或),&&是指只有两个操作数值都为ture(1)时,结果才为true,其他情况都是false(0),而||是只有两个操作数都是false时才会是false,其他情况都是ture

再来说优先级的问题,我是记住了一个口诀:

“单算移关与,异或逻条赋”
    单:单目运算符,自增(++)、自减(--)、逻辑非(!)、按位反(~)、取地址(&)、取值(*)

    算:算术运算符,乘(*)、除(/)、求余(%)级别高于加(+)、减(-)

    移:移位运算符,按位左移(<<)、按位右移(>>)

    关:关系运算符,小于(<)、大于(>)、大于等于(>=)、小于等于(<=) 高于 等于(==)、不等于(!=)

    与:按位与运算符(&) 

    异:按位异或运算符(^)

    或:按位或运算符(|)

    逻:逻辑运算符,逻辑与(&&)高于逻辑或(&&)

    条:条件运算符(?:)

    赋:赋值运算符(*=、/=、%=、+=、-=、<<=、>>=、&=、^=、|=、!=、=)

原文链接:blog.csdn.net/sgbl888/art…

下面是老师给我们出的一道例题(ps:每次老师在课堂上出这种题,我都特别担心自己做不对,然后就真的做不对,,,)

int a,b,c;
a=b=c=5;
则执行语句:b+=++a&&++c>b;
后a,b,c的值是分别为:6,6,6

条件运算符

可以实现简单的选择功能,表达式为:表达式1?表达式2:表达式3

其中表达式一必须是bool类型,执行顺序为,先执行表达式1,若表达式1的值为true,则求解2,2的值最终的结果

下面是一个题,和条件运算符没什么关系,但是我很容易混

int a,b,c; a=1,b=2; c=(a++,a+=b,a+b); cout<<a<<","<<b<<","<<c<<endl;

执行顺序是先执行一,再二,最后的结果是三的结果,答案是:4,2,6

sizeof运算符:

用于计算某种类型的对象在内存中所占的字节数 ,即sizeof(类型名/表达式),但是要注意,求的是表达式的结果类型所占的字节数

cout<<sizeof 3+5.6f<<endl; 答案是:9.6,因为sizeof 3是4(int),5.6f就是5.6浮点数,答案是4+5.6=9.6

当然老师给我们出了衍生版:

cout<<sizeof(3+5.6f)<<endl;答案是:4,因为这就是一个计算浮点数所占内存的东西

数据类型的转换:

char————int————float————double

低—————————————————>高

执行下面代码,输出的是:0,并且注意这里的输出的z是float型的

int main() {

int x = 100;
int y = 200;
float z;
z = x / y;
cout<<z;

}

if语句实现选择结构:

语法上面没有什么好说的,就是比较关键的是if后面的条件语句的==不要写成=,然后也是可以是bool类型的,比如: `bool a;

if(a)`的意思就是如果a是ture

还有多重选择结构,比如if...else if,或者if if else else等等

switch语句

switch的执行顺序是:

首先计算switch语句小红表达式的值,然后在case中寻找值相等的表达式,由此开始执行,若没有找到符合的,则从default开始执行(每个case里记住加break,但并不是说没有break就不会跳出循环)

循环语句

有包括while语句,do..while,for循环,然后while和do while感觉没有特别多知识点(除了不会写程序),然后for考的比较多,

for循环

for(初始语句;表达式1;表达式2)

有一个语法注意是,初始语句,后面两个表达式都可以省略,但是;千万不能省略!!

在这里有一道题:for(;;)相当于===while(ture)相当于一个死循环

每个分号和分号之间不是只能有一个表达式,可以存在多个表达式的,for(i=0,j=100;i<=j;i++,j++)

循环结构与选择结构的嵌套

这里没有什么语法知识,就是程序的设计需要花费一些时间

其他控制语句

break语句

跳出当前循环,执行逻辑上的下一条语句

continue语句

作用是结束本次循环,然后根据条件判断是否执行下一次循环

第二章终于写完了,明天继续写第三章,希望能在考试前将这本书从头到尾翻一遍吧!

第三章:函数

函数的调用

编写一个求x的n次方的数

double power(double x, int n) {
	int b = 1;
	while (n--) {
		b *= x;
	}
	return b;
}

int main()
{
	cout << power(5, 2) << endl;
}

关于随机数种子,我觉得还挺好玩的,我这里用的是时间作为参数

#include <iostream>
using namespace std;
#include<cstdlib>
#include<ctime>

int main()
{
	srand(time(0));
	int j = rand();
	cout << j;
}

输入两个

int func1(int a) {
	return a * a;
}
int func2(int x, int y) {
	return func1(x) + func1(y);
}

int main()
{
	int a, b;
	cin >> a >> b;
	cout << func2(a, b) << endl;
}

递归调用

函数可以直接或间接的调用自身,称为递归调用,最典型的就是阶乘

#include <iostream>
using namespace std;

int func(int a) {
	if (a == 0||a==1)
		return 1;
	else {
			return a * func(a - 1);
	}
}

int main()
{
	cout << func(4);
}

递归调用我感觉我只有那么一点点皮毛,我在网上还搜到了什么皇后一堆问题,但是看不懂代码......但是老师给我们专门讲过有一个汉诺塔问题,没有太弄明白,现在去问一下老师,把代码放在这里看看明白了没有

#include <iostream>
using namespace std;

void move(char src, char dest) {
	cout << src << "--->" << dest << endl;
}

void hanoi(int n, char a, char b, char c) {
	if (n == 1)
		move(a, c);
	else {
		hanoi(n - 1, a, c, b);
		move(a, c);
		hanoi(n - 1, b, a, c);
	}
}

int main()
{
	int m;
	cin >> m;
	hanoi(m, 'a', 'b', 'c');
	return 0;
}

函数的参数传递

值传递

先来看一个代码:

#include <iostream>
using namespace std;

void swap(int a, int b) {
	int t = a;
	a = b;
	b = t;
	cout << "在swap函数里:" << endl;
	cout << "x: " << a << " y: " << b << endl << endl;
}

int main()
{
	int x = 5;
	int y = 10;
	cout << "x: " << x << " y: " << y << endl<<endl;
	swap(x, y);
	cout << endl;
	cout << "交换完以后在主函数里:" << endl;
	cout << "x: " << x << " y: " << y << endl;
}

可以看出,在这个交换函数里确实是实现了交换,但是在主函数里,x和y还是没有实现交换,所以可以看出函数调用时,传递的是实参(x,y)的值,是一个单向传递的过程,在这个函数里xy的值改变并不会影响外面xy的值,若想要真正实现,就需要用到引用传递

引用传递

引用可以看作是一个变量的别名,如果还是想要执行交换,只需要将上面的ab变成&a,&b即可 ,这里来看一个引用作为函数参数的一个代码:

#include <iostream>
using namespace std;

void fid(int a1, int& a2) {
	a1 += 100;
	a2 += 100;
	cout << "a1:" << a1 << endl;
	cout << "a2:" << a2 << endl;
}

int main()
{
	int b1 = 7 ;
	int b2 = 10;
	cout << "b1:" << b1 << endl << "b2:" << b2 << endl;
	fid(b1, b2);
	cout << "b1:" << b1 << endl << "b2:" << b2 << endl;
}

在这里输出的结果是:

b1:7 b2:10

a1:107 a2:110

b1:7 b2:110

由此可见值传递和引用传递的区别

带默认形参值的函数

函数在定义时可以预先声明默认的形参值,调用时如果给出了实参,就用实参初始化形参,如果没有给出实参,就用默认新参值,例如:

int add(int x=5,int y=6){
return x+y;
}

int main{
   add(10,20);
   add(10);
   add();
}

则输出的结果是:30,16,11

在这里注意,为什么第二个add里的10代表的是x呢?有默认值的形参必须在型参列表的最后,这里有几个例子:

int add(int x,int y=5,int z=10);--正确

int add(int x=1,int y=5,int z);---错误

int add(int x=1,int y,int z=10);---错误

这里又有一个知识点,在相同的作用域内,不允许在同一个函数的多个声明中对同一个参数默认值重复定义,即使相同也不行,例如:

int add(int x=5,int y=6);
int main(){
add();
return 0;
}
int add(int x/*=5*/,int y/*=6*/){
//这里不能再出现默认形参值了,为了清晰,可以标注说明
return x+y;
}

函数重载

是cpp的特性,大体意思是,两个以上的函数,具有相同的函数名,但是形参的个数和类型不同,这时候会发生函数的重载,编译器自己根据实参和形参来决定执行哪一个函数

在这里,函数的参数个数,参数类型和参数顺序中必须有一个不同才可以发生函数的重载

例如:

形参类型不同:

int add(int x,int y); float add(float x,float y);

形参个数不同:

int add(int x,int y); int add(int x,int y,int z);

但是不以返回值来区分函数:

int add(int x,int y); int add(int a,int b);

第四章:类与对象

前面的一些语法很熟悉了,直接从还不太熟的地方开始

类的成员函数

一般来说,类的成员函数是原型声明写在类的内部,具体实现是写在外部,在实现时,语法为:

返回值类型 类名::函数成员名(参数表){

函数体

}

构造函数和析构函数

构造函数

构造函数的意义是在对象被建立的时候,利用特定的值构造对象,将对象初始化为一个特定的状态,有一点,构造函数在对象被创建的时候将被自动调用,并且一旦定义了构造函数,除非我们自己再定义一个默认的构造函数,否则构造类将没有默认构造函数

复制构造函数

复制构造函数时一种特殊的构造函数,其形参是本类对象的引用,其作用是用一个已经存在的对象去初始化一个同类的对象,语法形式:

类名(类名&对象名);

复制构造函数被调用的几种情况:
(1)

当用类的一个对象去初始化该类的另一个对象时,例如:

int main(){
   point a(1,2);
   point b(a);//用对象a去初始化对象b,复制构造函数被调用
   point c=a;//用对象a初始化对象c,复制构造函数被调用
}
(2)

如果函数的形参是类的对象,调用函数时,进行形参和实参结合时,例如:

void f(point p){
  cout<<p.getX()<<endl;
}
int main(){
point a(1,2);
f(a);//函数的形参为类的对象,当调用函数时,复制构造函数被调用
}
(3)

如果返回值是类的对象,函数执行完成返回调用者时,例如:

point g(){
point a(1,2);
return a;//函数的返回值是类对象,返回函数值时,调用
}
int main(){
point b;
b=g();
}

析构函数

析构函数是在对象的生存期即将结束的时刻被自动调用的,调用以后对象消失,相应的内存空间也释放,这里会出题:

函数体为空的析构函数未必不做任何事

第五章:数据的共享与保护:

静态生存期

如果对象的生存期与程序的运行期相同,我们称它具有静态生存期,在文件作用域中声明的对象都是具有静态生存期的,如果想要函数内部的对象具有静态生存期,则需要使用关键字static,例如:

static int i;

在这里要注意,静态数据成员并不属于任何一个对象,他是属于类的,因此可以通过类名来进行访问“类名::标识符”

静态数据成员一般需要在类定义之外再加定义,声明在类内,初始化和定义在类外,来看一个例题,关于Point类的

#include <iostream>
using namespace std;

class point {
public:
	point(int x = 0, int y = 0) :x(x), y(y) {
		count++;
	}
	point(point& p) {
		x = p.x;
		y = p.y;
		count++;
	}
	~point() {
		count--;
	}
	int getx() {
		return x;
	}
	int gety() {
		return y;
	}
	void shoucount() {
		cout << "number:" << count << endl;
	}
private:
	int x, y;
	static int count;
};
int point::count = 0;

int main()
{
	point a(4, 5);
	cout << "point a" << a.getx() << "," << a.gety() << endl;
	a.shoucount();

	point b(a);
	cout << "point b:" << b.getx() << "," << b.getx()<<endl;
	b.shoucount();
	return 0;
}

静态函数成员

在刚刚那个程序里,函数showcount是专门来显示静态成员count,但是如果count的初始值是0,该怎么输出呢(因为一旦建立对象count的值就是1),对普通函数的调用必须要用到对象名,直接用类名调用,比如point::showcount();编译会出错

这时候我们可以用到static关键字将函数设为静态函数成员,这个函数由同一个类的对象共有,也就是说不属于任何一个对象,属于这个类的

静态成员函数可以通过类名或对象名来调用,但是一般习惯于用类名来调用

静态成员函数可以直接访问该类的静态数据和函数成员,而访问非静态成员必须通过函数名,例如:
class A{
public:
static void f(A a);
private:
int x;};
void A::f(A a){
cout<<x;//错误
cout<<a.x;//正确

友元

简单理解为一种共享机制

友元函数

友元函数是在类中用关键字friend修饰的非成员函数,可以是一个普通的函数,也可以是其他类的成员函数,虽然不是本类的成员函数,但可以通过对象名来访问该类的私有成员

共享数据的保护

常成员函数

使用const修饰的函数称为常成员函数,类型说明符 函数名(参数表)const

记住,在函数定义部分也要加上const

如果将一个对象说明为常对象,则通过该对象只能调用它的常函数成员而不能调用其他成员函数

const关键字可以用于重载函数的区分

常数据成员

例如:

private:
const int a;
static const int b;}
const int A::b=10;
常数据成员不能在声明时赋值(普通函数也是),常数据成员必须在构造函数的初始化列表里初始化

第六章:数组,指针与字符串

数组作为函数参数

当使用数组名作为函数参数时,实参和形参都应该是数组名,且类型要相同,和普通变量做参数不同,使用数组名传递数据时,传递的是地址。

对象数组

对象数组的元素是对象,在初始化之际,会调用形参类型匹配的构造函数

指针

与地址相关的运算---‘*’和‘&’

是指针运算符,表示获取指针所指向的变量的值,是一个一元操作符,如ptr表示指针ptr所指向的int型数据的值 &是取地址运算符,用来得到一个对象的地址,如&i可以得到变量i的储存单元地址

注意关于&的运算

在int &i;中表示的是引用,在等号右边表示的是对象的地址,如int *pa,*pb=&b;pa=&a;

指针的赋值

(1)在定义指针的同时进行初始化赋值,语法形式为: 数据类型 *指针名=初始地址;

(2)在定义之后,单独使用赋值语句,赋值语句的语法为: 指针名=地址;

一个数组,可以用它的名称来直接表示它的起始地址,例如: int a[10];int*ptr=a;

啊实在写不下去了,那就先写到这里吧,随后有机会(如果还有的话)再继续写吧!!!