栏目分类:
子分类:
返回
名师互学网用户登录
快速导航关闭
当前搜索
当前分类
子分类
实用工具
热门搜索
名师互学网 > IT > 软件开发 > 后端开发 > C/C++/C#

c++深入理解精髓

C/C++/C# 更新时间: 发布时间: IT归档 最新发布 模块sitemap 名妆网 法律咨询 聚返吧 英语巴士网 伯小乐 网商动力

c++深入理解精髓

目录

c++编程基础

第一节包括:

  • 一些基础类型:bool int char float
  • 算术运算符,关系运算符,逻辑运算符
  • 条件分支和循环控制语句
  • 一些复合类型
  • 一套标准,通用的抽象化库

1.1 如何编写一个程序呢:

c++程序都是从main() 函数开始执行,形式如下:

int main()
{
//.....
}

int 是c++程序语言的关键字--具有特殊意义的名字。

函数是一块独立的程序代码序列能够执行一些运算,由四部分组成:1 返回类型2 函数名3 参数列表4 函数体

main 函数返回非零的值表示程序执行有无,正确是return 0;

函数的参数列表()括住置于函数名之后,可以为空;

函数的主题是由{} ;

//单行注释 多行注释

基础数据类型:bool char int float 

class 的定义有两部分,分别写在不同的文件,其中所谓的头文件用来声明class提供的各种行为,另一文件包含行为的实现。

#include

我们可以写个例子:

#include
using namespace std;//标准库所提供的任何事物都被封装在命名空间std内。
#include//引入头文件
int main()
{
string name;
cin>>name ;//输入
cout< 

 1.2对象的定义与初始化

对象的名字可以是有任何字母,数字,下滑线的组合。对象名字不能以数字开头。

单一声明语句中定义多个对象其间用逗号分隔。

int  a=0,b=0;

 初始化语法:
 

int a(0);
stirng name="Tom";

c++ 支持三种浮点数类型

float 单精度
double 双精度
long double 长双精度

转义字符:

'n' 换行符
't' 制表符
'' null
''' 单引号
'\' 反斜线

Bool 对象 其值可以是true/false;

const int a=3;被它定义的变量获得初始值之后,无法再改变。

1.3 表达式

算术运算符 + - * / % 

条件运算符C ?A:B 如果C为true执行A,否则执行B;

复合运算符 += -= *= /=

关系运算符> < >= <= ==  !=

if () {};

if () {}else {};

if () {}if else() {}else {};

 逻辑运算符:!   &&  ||(会出现短路)

//运算符优先级从高到低
	!
	* / %
	+ -
	< > <= >=
	== !=
	&&
	||
	=

条件语句

switch ()
	{
	case 1:
		break:
	case 2:
		break;
	default:
		break;
	}

循环语句

	while () {};
	break;
	continue:

1.5 Array和vector

#include
using namespace std;
#include
#include
int main()
{
	int arr[] = { 1,2,3,4,5 };//自动推断arr的长度
	vectorv = { 1,2,3,4,5 };
	arraya = { 1,2,3,4,5 };// 第一个是表示存储类型,第二个是存储元素的个数
	for (int i = 0; i < v.size(); i++)
	{
		cout << v[i];
	}
	cout << endl;
	for (auto i : a)
	{
		cout << i;
	}
	cout << endl;

	return 0;
}

1.6指针带弹性

	int* p = nullptr;
	int a = 1024;
	p = &a;
	//*p是求a的值
	//p存储的是a的地址
	//虽然指针可以不指向空,防止内存泄漏将指针指向nullptr;

1.7 文件的读写

要对文件进行读写首先包含头文件#include

#include
using namespace std;
#include

int main()
{
	ofstream ofs("123.txt");
	ofs << "neltelan";//向123.txt写入neltelan
	ofs.close();//关闭文件
	//声明ofs的同时,如果文件并不存在便会有一个文件产生出来并共输出使用。若存在就打开并用于输出。
	ifstream ifs("123.txt");//类似ofstream 供输入
	char a[1024] = { 0 };
	while (ifs.getline(a, sizeof(a)))//读取文件内容
	{
		cout << a << endl;

	}
	ifs.close();
	

	return 0;
}

 

面向过程中的编程风格

2.1 如何编写函数

函数四部分组成:

  1. 1返回类型。没有返回值的类型为void
  2. 2函数名。简明字义
  3. 3参数列表。函数参数扮演者占位符的角色。
  4. 4函数体。操作本身的工作逻辑的实现内容。
  5. 函数必须先被声明,然后才能被使用。函数的声明不必提供函数体。但必须指明返回类型,函数名,以及参数列表。
  6. double fun(double x);//函数声明
    #include
    using namespace std;
    #include
    double fun(double x);
    int main()
    {
    	cout << "fun(4) = " << fun(4) << endl;
    
    	return 0;
    }
    double fun(double x)//函数定义
    {
    	return x * x * x;
    }
    

    2.2 调用函数

  7. 我们以一个vector 内的整数的排序;

  8. #include
    using namespace std;
    #include
    void display(vector&vec);
    void swap(int &val1, int &val2);
    void bubble_sort(vector&vec);
    int main()
    {
    	vectorv = { 1,5,3,7,3,8,9,2,3,5 };
    	
    	bubble_sort(v);
    	display(v);
    
    	return 0;
    }
    void display(vector&vec)
    {
    	for (int i = 0; i < vec.size(); i++)
    	{
    		cout << vec[i] << " ";
    		cout << endl;
    	}
    }
    
    void swap(int &val1, int &val2)
    {
    	int temp = val1;
    	val1 = val2;
    	val2 = temp;
    }
    void bubble_sort(vector &vec)
    {
    	for (int i = 0; i < vec.size(); i++)
    	{
    		for (int j = i+1; j < vec.size(); j++)
    		{
    			if (vec[i] > vec[j ])
    			{
    				swap(vec[i], vec[j]);
    			}
    		}
    	}
    }
    

     指针和引用

  9. int a =1024;
    int *pi=&a;//pi指向一个int对象
    int &val=a;//val是a 的别名,引用从一而终

    引用的方式将对象作为函数参数传入时,对象本身并不会复制出另一份-复制的是对象的地址。

  10. 将参数声明为引用的理由之一:希望得以直接对所传对象进行修改。

  11. 理由之二:降低复制大型对象的额外负担。

  12. void display(vector&vec)//避免复制占用大量内存
    {
    	for (int i = 0; i < vec.size(); i++)
    	{
    		cout << vec[i] << " ";
    		cout << endl;
    	}
    }

    作用域及范围

  13. 函数内定义的对象,只存在于函数执行期间。如果返回局部变量的地址会导致运行错误。局部变量放在堆栈上,当函数执行完毕,这块区域将会被弃置。

  14. 对象在程序内的存活区域称为该对象的作用域;全局变量会自动初始化为0;局部变量不予初始化。

  15. 动态内存管理

  16. new和delete运算符:

  17. int *p;
    p=new int;//在堆区开辟int大小的内存
    p=new int(111)//指定初始值;
    int *pi=new int[10];//分配10个int大小未初始化的空间
    
    
    delete pi//释放。如未释放后果不堪设想
    数组的释放
    delete []pi;

    2.3提供默认参数值

  18. 默认参数指的是当函数调用中省略了实参时自动使用的一个值;

  19. 对于带参数列表的函数必须从右往左添加默认值。

  20. #include
    using namespace std;
    int fun(int a, int b = 100);
    int main()
    {
    	
    	fun(20);
    	fun(1000, 1000);
    
    	return 0;
    }
    int fun(int a, int b )
    {
    	cout << "a = " << a << endl;
    	cout << "b = " << b << endl;
    	return 0;
    }
    

  21.  

    2.4 使用局部静态对象

    因为局部对象会在每次调用函数时建立。并在函数调用结束时被弃置。因此我们使用局部静态对象。局部静态对象可以返回引用。

    const vector* fun(int a)
    {
    	static vectorelems;
    	return &elems;
    }
    

     局部静态对象所存储的空间,即使不同的函数调用过程中,依然持续存在。

  22. 2.5 声明inline函数

  23. 将函数声明为inline函数表示要求编译器在每个函数调用调用点上将函数展开。

  24. 一般最合适声明inline的函数,体积小常被调用,所从事的计算不复杂。

  25. inline定义常放在头文件中。

  26. 2.6 重载函数

  27. 重载:参数列表不相同的两个或多个函数,可以拥有相同的函数名称

  28.     void fun(char ch);
    	void fun(const string&);
    	void fun(const string&, int);
    	void fun(const string&, int, int);

    编译器如何区别-->它会将调用者提供的实际参数拿来和每个重载函数的参数比对,找出最合适的。注意编辑器无法根据返回类型来区分两个具有相同的函数。

  29. 2.7 函数模板

  30. 函数模板代表一个函数的家族:

  31. template 
    void swap(T& a, T& b)
    {
    	int temp = a;
    	a = b;
    	b = temp;
    }
    //T 可以是int float long double 等....

    2.9 设定头文件

  32. 再调用一个函数之前,必须先声明,让程序知道它的存在。为了减少重复操作,将所有声明集中到一个.h 结尾的文件。可供多个程序使用,使用时只需#include<它>就可以了;声明可以多次但定义只需一次。

  33. 为啥会有#include<> 和 #include" "呢-->如果此文件被认定为标准的或项目专属的头文件用<>;

  34. 用户的头文件用" ";

泛型编程风格

指针的算术运算

如果给定一个vector用来存储整数,找到value并必须返回指针指向的值:

	int* find(const  vector*vec, int val)
	{
		for (int i = 0; i < vec.size(); i++)
		
			if (vec[i] == val)
			
				return &vec[i];
		
	}

如何实现一个泛型find()的呢

template
elemtype* find(const vector&vec, const elemtype & val)
{
	for (int i = 0; i < vec.size(); i++)
	{
		if (vec[i] == val)
			return &vec[i];
	}
	return 0;
}

如果我们用的是数组不是向量上述模板不适合

当数组被传给函数,或函数返回仅有第一个元素的地址会被传递。

int fun(int arr[10]){};
int fun1(int *arr){};//两个传递数组作用相同

 数组查找泛型:

template
elemtype* find(const elemtype * arr, int size, const elemtype & val)
{
	if (!arr || size < 1)//判断是否数组合理
	{
		return 0;
	}
	for (int i = 0; i < size; i++)
	{
		if (arr[i] == val)
		{
			return &arr[i];
		}
	}
	return 0;
}

3.2 iterator

写一个display():

template
void display(const vector&vec, ostream & os)
{
	vector::const_iteator it1 = vec.begin();
	vector::const_iteator it2 = vec.end();
	for (; it1 != it2; ++it)
	{
		os << *it << " ";
		os << endl;
	}
}
//const_iteator只读不可修改,iteator可读可写

 

 

基于对象的编程风格

 类是一种将抽象转换为用户定义类型的c++工具,它将数据表示和操作数据的方法组合一个整洁的包。

类声明:以数据成员的方式描述数据部分,以成员函数的方式描述公有接口

类的方法定义:描述如何实现类的成员函数

c++将接口放在头文件中,并将实现放在源代码文件中

不必在类声明中使用关键字private因为这是类对象默认访问控制

class world
{
	float mass;
	char name[10];
public:
	void fun();
};

 

类和结构的区别:结构的默认访问类型是public,类的是private

实现类的成员函数

定义成员函数是有作用域解析符(::)来标识所属类

类方法可以访问类的private组件

#pragma once
#include
#include
using namespace std;
class student
{
	string name;
	int age;
public:
	void studentset(string, int);
	void display();

};

我们可以先实现函数的定义在.cpp文件中

#include"test.h"
void student::studentset(string name, int age)
{
	this->name = name;//this 是区分name,右边name是传参进来的,左边的name是调用本函数的对象里的name
	this->age = age;
}
void student::display()
{
	cout <<"姓名:" << this->name <<"年龄:" << this->age << endl;
}
#include"test.h"
int main()
{
	student one;
	student two;
	//创建每一个新对象都有自己的新空间,由于存储其内部变量和类成员,但同一个类的所有对象共享同一组类方法,及每一个方法只有一个副本。
	one.studentset("小米", 23);
	two.studentset("小花", 34);
	one.display();
	two.display();
	return 0;
}

类的定义

类的定义必须用分号结尾;

1.类的成员

成员可以是:成员函数(方法,构造和析构函数),成员变量(数据成员),成员枚举,类型别名和嵌套类。

最好将不改变对象的成员函数声明为const.成员函数和数据成员不能同名。

2.访问控制

三种:public protected private

3.声明顺序

可以使用任何顺序声明成员和访问控制说明符,还可以重复使用访问说明符;

class sheet
{
public:
	void fun();
private :
	double value;
public:
	double getvalue();
};

4.类内成员初始化

可直接在类定义中初始化成员变量。

class student
{
	string name="Tom";
	int age=10;
public:
	void studentset(string, int);
	void display();

};

5.定义方法

通常类定义在头文件中,方法定义在包含头文件的源文件中。 

 

​
#include"test.h"
void student::studentset(string name, int age)
{
	this->name = name;//this 是区分name,右边name是传参进来的,左边的name是调用本函数的对象里的name
	this->age = age;
}
void student::display()
{
	cout <<"姓名:" << this->name <<"年龄:" << this->age << endl;
}

​

注意每个方法名之前都出现了类名和作用域解析符。 

如何实现一个类

我们以栈stack为例:

class Stack
{
public://公有接口
	bool push(const string&);
	bool pop(const string& elem);
	bool peek(string& elem);
	bool empty();
	bool full();
	int size() { return stack.size(); };

private://私有接口
	vector stack;
};

class 定义有两部分组成:class声明以及在声明之后的主题部分有一个大括号以分号结尾。 

bool Stack::empty()
{
	return stack.empty();
}

在.cpp 文件内定义Stack里的成员函数,::指明函数属于哪个类。

4.2 构造和析构函数

构造函数名必须与类名相同,不指定返回值类型,可以发生重载。

class Triangular
{
public:
	Triangular();//无参构造
	Triangular(int len);//有参构造
	Triangular(Triangular&)//拷贝构造

};

当class object定义出来后,编辑器自动根据获得的参数,调用对应的构造函数。

没有构造函数编辑器会自动提供构造函数。

与构造函数类似的析构函数。

严格规定~类名(){}为析构函数。它不可以重载。  

4.3 mutable 和 const 

int sum(const Triangular &tain)
{
     //....这里面不可以对tain进行修改
}
class Triangular
{
public:
	Triangular();//无参构造
	Triangular(int len);//有参构造
	Triangular(Triangular&);//拷贝构造
	int len()const { return length; };//在成员函数后面加const表示这个函数不会更改类对象的内容。
	int po()const { return pos; };
	int ne()const { return next; };

private:
	int length;
	int pos;
	int next;

};

Mutable 数据成员

class Trianguar
{
public:
	bool next(int& val)const;
	void next_reset()const { _next = _beg_pos - 1; };
private:
	mutable int _next;//虽然成员函数后有const但依然可以修改_next变量。
	int _beg_pos;
	int _length;
};

4.4This 指针

我们看一个拷贝构造函数:

Triangular& Triangular::copy(const Triangular& rhs)
{
    if(this!=&rhs)//检查两个对象是否相同
	_length = rhs._length;
	return *this;//this 指向调用者
}

this指针系在成员函数内用来指向其调用者(一个对象)。

持续更新!!!!!!


 

 

转载请注明:文章转载自 www.mshxw.com
本文地址:https://www.mshxw.com/it/849863.html
我们一直用心在做
关于我们 文章归档 网站地图 联系我们

版权所有 (c)2021-2022 MSHXW.COM

ICP备案号:晋ICP备2021003244-6号