基本C++-------------2018.6.25

从头再来一遍,注重细节,注重基本功。

c++是一种编译型语言。

可执行文件无法移植  源代码具有可移植性。

C++提供的标准库组件也是非常普通的C++代码。

C++是一种静态类型语言,编译器在处理任何实体时必须清楚它的类型


Hello , world!

每一个C++程序中有且只有一个名为main()的全局函数,在执行程序时首先执行该函数,main()函数的非零返回值程序返回给系统的,表示程序执行失败

#include<iostream>

int main(){
	std::cout << "Hello, World!\n";
}

#include<iostream>指示编译器把iostream中涉及标准流I/O功能的声明包含进来。

std::cout标准输出流 “Hello, World!\n”字符串字面值  \n是转义字符换行  <<表示把第二个参数写入第一个参数。

std::指定名字cout所在的标准库名字空间

基本上所有可执行代码都要放在函数中,并且被main()函数直接或间接地调用

C++批量注释代码段取消注释代码段快捷键

1,先选中要注释的代码段 
2,按住ctrl+k+c注释本段代码 
3,按住ctrl+k+u取消注释本段代码

#include<iostream>
using namespace std;

double square(double x){
	return x*x;
}

void print_square(double x){
	cout << "the square of " << x << " is " << square(x) << "\n";
}

int main(){
	/*std::cout << "hello, world!\n";*/
	print_square(1.234);
}

需要注意的是:C++函数内部不能定义普通函数


类型、变量和算术运算

声明是一条语句,负责为程序引入一个新的名字,并指定该命名实体的类型

类型:决定了操作。

对象:存放某类型值的内存空间

一组二进制位具体的含义由其类型决定

变量:是一个命名的对象

基本类型:

 bool-----true false

char-----'a' '9'

int-----1, 42 

double----3.14 299793.0 

类型的实际尺寸是依赖于实现的(即在不同的机器上可能不同),使用sizeof()可以得到,比如sizeof(char)为1,这里的1表示1byte, 8 bit。

算术运算符   比较运算符  

在赋值运算和算术运算中,C++会在基本类型间进行类型转换

初始化

double d1 = 2.3;

double d1{2.3};

complex<double> z=1;

complex<double> z2{d1,d2};   //complex是类模板 复数 实部和虚部是double

complex<double> z3={1,2}; //使用{}初始化的时候=是可选的

vector<int> v{1,2,3,4,5,6};

使用{}方式的好处在于---可以确保不会发生某些可能导致信息丢失的类型转换


常量在声明时不能不进行初始化!

普通变量也最好进行初始化!

在定义一个变量时,若变量的类型可以由初始化器推断得到,则无需显式指定其类型

auto b = true;  //bool

auto ch = 'x';  //char

auto i = 123; //int

auto d = 1.2;   //double

auto 在泛型编程中会经常使用到!!!


常量

const: 我承诺不改变这个值 

int var = 17; const double max3 = 1.4 * square(var);  是正确的,它是运行时求值

constexpr:  在编译时求值 说明常量 将数据存于只读内存中,提高性能。

而 int var = 17; constexpr double max3 = 1.4 * square(var);  是错误的,1.4 * square(var)不是常量表达式。

如果某个函数用在常量表达式中,则其必须定义成constexpr.

constexpr double square(double x){return x*x;}

注意:constexpr函数可以接受非常量实参,但此时其结果将不会是一个常量表达式。

编译时求值对程序的性能非常重要,同时不变性概念也是程序设计中要考虑的一个重要问题。


检验和循环

bool accept(){
	cout << "do you want to proceed(y or n)?\n";

	char answer = 0;
	cin >> answer;

	/*if (answer == 'y') return true;
	return false;*/

	switch (answer)
	{
	case 'y':
		return true;
	case 'n':
		return false;
	default:
		cout << "i will take that for a no\n";
		return false;
	}
}
C++提供了 一套用于表示 选择循环的常规语句。


指针、数组和循环

声明数组 char v[6];    //含有6个字符的数组  ---v包含了6个元素v[0]到v[5]数组的大小必须是常量表达式

声明指针 char* p; //该指针指向字符  指针变量中存放的是一个相应类型对象的地址(内存地址)

char* p = &v[3];    //p指向v的第四个元素

char x = *p;   //取出其中的内容

前置一元运算符*表示“.....的内容” 前置一元运算符&表示“......的地址”

范围for语句

void print(){
	int v[] = { 0, 1, 2, 3, 4, 5, 6, 7, 8, 9 }; //列表初始化数组时无需指定其大小

	for (auto x : v)    //范围for语句
		cout << x << '\n';
}

如果我们不希望把v的值拷贝到x中,而只想令x指向某个元素,则

void print(){
	int v[] = { 0, 1, 2, 3, 4, 5, 6, 7, 8, 9 }; //列表初始化数组时无需指定其大小

	for (auto& x : v)    //范围for语句
		cout << x << '\n';
}

一元后置运算符&表示“....”的引用

引用类似于指针,唯一的区别是我们不需要使用前置运算符*访问引用的值

确保指针永远指向某一个对象


没有对象可指的时候(比如列表的末尾),则可以令指针取值为nullptr("空指针")。所有指针类型都共享同一个nullptr

在旧式代码中,0NULL都可以用来替代nullptr的功能,但使用nullptr可以避免在整数(0或NULL)和指针(nullptr)之间发生混淆。

指针指向一个字符数组,该数组的结尾处是0.

注意:有很多时候,莫名其妙的错误是由于 括号  等的中英文输入的错误!!!!!!

int count_x(char* p, char x){  //统计P[]中出现x的次数
	if (p == nullptr) return 0;      //看指针是否是空
	int count = 0;
	for (; *p != 0;++p)   //判断是否达到字符数组尾部  *p != 0  尾部为0
		if (*p == x)
			++count;
	return count;
}


用户自定义类型

内置类型通过 基本类型const修饰符、 声明运算符构造,偏重 底层编程不能向程序员提供书写高级应用程序的上层特性

故,c++扩充了这些内置类型和操作,引入了成熟的抽象机制

C++抽象机制的目的是让程序员能够设计并实现他们自己的数据类型,称为用户自定义类型,比如枚举等。

主要在于用户自定义类型设计实现使用



结构

new运算符从一块名为 自由存储(free store){又称 动态内存(dynamic memory)}或 堆(heap)的区域分配内存。

访问struct成员有两种方法,一种用. , 一种用->

struct Vector{    //构建一种新类型的第一步是把所需的元素组织成一种数据结构
	int sz;   //元素的个数
	double* elem;  //指向元素的指针
};

void vector_init(Vector& v, int s){     //初始化函数  引用方式
	v.elem = new double[s];     //分配一个数组,它包含s个double值 数组的头地址给了指针 
	v.sz = s;
}

double read_and_sum(int s){
	Vector v;
	vector_init(v, s);
	for (int i = 0; i != s; ++i)
		cin >> v.elem[i];       //v.elem可以看成是数组名

	double sum = 0;
	for (int i = 0; i != s; ++i){
		sum += v.elem[i];
	}
	return sum;
}
cout<<read_and_sum(4);

以Vector 和标准库中的vector为例,目的:

1.展现语言特性程序设计技术

2.帮助读者学会使用这些标准库组件

学会了之后,尽量直接使用vector 、string等标准库组件



上面的做法是将数据操作进行了分割

下面的做法是将类型的接口与其实现分离开来,称为。一般方法是public,成员变量是private的。

外界只能调用public  public方法可以调用private变量

在这里,Vector 对象是一个 句柄,包含了 指向元素的指针以及 元素的个数

即:一个固定大小的句柄指向位于别处(通过new分配的自由空间)的一组可变数量的数据。

class Vector{
public:
	Vector(int s) :elem{ new double[s] }, sz{ s }{} //初始化  使用了成员初始化器列表来初始化成员
	double& operator[](int i){ return elem[i]; }  //通过下标访问
	int size(){ return sz; }
private:
	double* elem;   //指向元素的指针
	int sz;    //元素的个数
};

double read_and_sum(int s){
	Vector v(s);     //调用接口  构造函数(用来构造类的对象的函数) 作用是初始化类的对象
	for (int i = 0; i != v.size(); ++i)
		cin >> v[i];

	double sum = 0;
	for (int i = 0; i != v.size(); ++i)
		sum += v[i];
	return sum;
}
cout << read_and_sum(5);

目前还没有涉及:

1.错误处理

2.也没有提供一种机制来“归还”通过new获取的double数组,即析构函数的问题。


枚举

除了类之外,C++还提供了另外一种 简单形式的用户自定义类型--- 枚举

enum class【强类型】 Color {red, blue, green};

enum class Traffic_light {green, yellow, red};

Color col = Color::red;

Traffic_light light = Traffic_light::red;

通过使用有指代意义的枚举值名字可提高代码的可读性,降低出错的风险。


模块化

C++程序可能包含许多独立开发的部分,比如:函数用户自定义类型类层次模板

构建C++程序的关键是 清晰地定义这些组成成分之间的相互关系

第一步,也是最重要的一步是:将某个部分的接口和实现分离开来

在C++中,使用声明来描述接口

而函数体,即函数的定义位于其他某处

分离编译

用户代码只能看到所有类型和函数的声明。他们的定义则放置在分离的源代码中,并被分别编译

一般情况下,我们通常将描述 模块接口的声明放在一个特定的文件【 .h文件】中,文件名指示用途,称为 头文件,用户将其 包含include进程序以访问其接口。

如果是自定义的 #include "Vector.h"

如果是标准库 #include <cmath>    一个库通常是一组分类编译的代码片段(函数)的集合

为了帮助编译器确保一致性负责提供Vector实现部分.cpp文件同样应该包含提供接口的.h文件

分类编译机制在实际的编程过程中非常重要,最好的方法是最大限度地模块化逻辑上通过语言特性描述模块,而后在物理上通过划分文件、分类编译来充分利用模块化。






  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值