首页 > 编程 > C++ > 正文

C++学习笔记

2019-11-06 07:19:52
字体:
来源:转载
供稿:网友
> (1)定义常量 const datatype CONSTANTNAME=value;例如定义一个int常量,其值是1;const int CONSTNUMBER=1;[一般常量我们喜欢用大写字母表示](2)指数运算符。pow(a,b)用来计算a的b次方是多少!pow是在cmath库文件中定义的函数。(3)数值类型的转换通过使用转换运算符static_cast<type>(value);注意:类型转换并不改变被转换变量的值。例如:double d=5.5;int i=static_cast(5.5);转换完之后的i=5,d依旧是5.5;(4)string字符串的输入c++在string头文件中提供了getline函数,默认情况下,输入是以空白字符结束,如果你想输入Happy New Year就必须使用getline函数。具体使用示例:string city;cout<<"enter your city name"<<endl;getline(cin,city,'/n');//这表示以'/n’来表示输入,由于第三个参数默认值是'/n’,所以可以省略,变成getline(cin,city);(5)函数原型。如果main函数在前,而main函数要使用的函数在main函数之后才定义,需要在程序中声明要使用的函数的原型。#include<iostream>using namspace std;int test(int i);//这就是函数原型int main(){......test(5);return 0;}int test(int i){rerurn i;}(6)缺省参数缺省参数就相当于默认参数。例如:void test(int i=5){......}如果调用这个函数时没有传入参数I是多少,则默认是5。(7)数组的声明和初始化。例如:int mylist[2]={2,3};不能这样子。int mylist[2];mylist={2,3}因为数组的初始化语句只能在一条语句中完成。(8)数组作为函数参数。例子:void test(int list[]){............}使用方式:int a[]={2,3,4,5,6};test(a);如果在函数参数里面的int list[]前面加上了const就不能在函数里面修改传入的数组。例如:void test(const int list[]){list[0]=100;//出错,不能修改出入进来的数组的值}(9)数组不可以作为函数返回值返回。例如:int [] test(const int list[]){......}c++中是不允许的。如果实现类似返回数组的功能可以使用两个数组。例如:void test(const int list[],int newlist){for(int i=0;i<list.size();i++){list[i]=newlist[i]}}(10)字符串相关函数strlrn(char s[]); 返回字符串的长度,即在空终结符之前的字符个数。strcpy(char s1[],const chars2[]); 将字符串s2复制到s1中去。strncpy(char s1[],char s2[],size_t n); 将字符串s2前n个符号复制到S1中。strcat(char s1[],const char s2[]);把字符串s2拼接到s1之后。strncat(cgar s1[],char s2[],size_t n); 将字符串s2前n个符号拼接到S1之后。(11)类定义和类实现的分离。类定义:定义在Circle.h文件之中class Circle{public:double radius;Circle();Circle(double r);double getRadius();}类实现:实现在Circle.cpp文件之中注意在类文件实现的文件Circle.cpp文件的头部要包含以下的文件。#include "Circle.h";Circle::Circle(){ radius=1;}.............(12)使用typedef来定义同类型。例如:typedef int integer; 这样可以使用integer来声明int变量。例如:integer a=10; 相当于 int a=10;(13) c++中函数的参数有按值传递和引用传递两种 void test(int n1,int n2){ }//按值传递。 void test(int &n1,int $n2){ }//引用传递。有什么区别呢?按值传递的方式有很大的局限性。例如函数swap( ):void swap(int n1,int n2){ cout<<"inside swap and before invoking n1 is''<<n1<<"n2 is"<<n2<<endl;int temp=n1;n1=n2;n2=temp;cout<<"inside swap,after invoking n1 is"<<n1<<"n2 is"<<n2<<endl;}//这是按值传递参数,那么来看一下按值传递的方式的局限性在哪里。在main函数中调用这个函数。int main(){ int num1=1; int num2=2; cout<<"before nvoking num1 is"<<num1<<"num2 is"<<num2<<endl; swap(num1.num2); cout<<"after invoking num1 is"<<num1<<"num2 is"<<num2<<endl; }输出结果是:(1)before nvoking num1 is 1 num2 is 2;(2)inside swap and before invoking n1 is 1 n2 is 2;(3)inside swap after invoking n1 is 2 n2 is 1;(4)after nvoking num1 is 1 num2 is 2;可以看到只是函数内部的n1和N2被交换了值,而num1和num2在调用之前和调用之后的值依旧不变。这是因为实际上num1和num2的值被传递给了n1和n2。当n1和n2有了值以后在内存中的地址与num1和num2的地址是不一样的,所以改变n1,n2的值与num1和num2无关。【按值传递的局限性就体现在了这里】既是把swap函数变成了swap(int num1,int num2){.......}//把传入的参数的名字变成num1,num2.也还是一样的结果,这与参数名字无关。所以可以采用引用传递来实现交换之后num1和num2的值也变了。了解引用传递之前,先来了解一下引用变量。引用变量是一种特殊的变量,可以通过引用变量来访问和修改存储在变量中的原数据。声明一个引用变量,可以在变量名前或者是数据类型之后加上一个'&'符号。例如:int &r; int& r;【一般采用这一种】把swap函数变成swap(int& n1,int& n2){......}这样调用swap函数之后的num1和num2就会交换数据了。(14)指针学习理解指针第一步: 声明指针只需要在声明指向的数据类型之后加上*。 例如 int a;【声明一个int类型的变量a】 int * a;【声明了一个指向int类型数据的内存地址的指针a】 指针变量保存的是内存地址,运算符*可以访问指针指向的内存地址的数据。 &是地址运算符。 假设定义了一个指针 int * count,则&count是count的地址。 可以使用&将一个指针的地址赋给另一个指针。 例如: pcount=&count; 指针可以在声明是赋值,也可以在声明之后赋值。第二步: 常量指针。 常量指针指向的是一个不变的内存位置,但是该内存位置处的实际值是可以更改的。 声明一个常量指针 int const * p;p就是一个常量指针。 可以修改p指向的内存地址的值,例如*p=10; 也可以使得一个常量指针指向内存位置处的实际值不可以改变,变成了const int const * p=10; 第一个const是常量数据,第二个const是常量指针。第三步: 函数调用的时候传递指针参数。 继续来讲swap函数,下面定义两个swap函数,分别为swap1(),swap2()。 swap1(int* p1,int* p2){ int temp=*p1; *p1=*p2; *p2=temp; }//相当于按值传递 swap2(int* &p1,int* &p2){ int* temp=p1; p1=p2; p2=temp; }//相当于引用传递,唯一需要注意的是int * &p1之后是地址的传递,不是值的传递了!!!再说一前面说数组传参数的问题。void test(int list[])可以被替换为void test(int* list,int size);也就是说函数中的数组参数都可以用指针参数来替换。第四步:从函数中返回指针。例如:int* reverse(int* list,int size){for(int i=0,j=size-1;i<j;i++,j--){int temp=lits[j];list[j]=list[i];list[i]=temp;}return list;}相对应的原型可以写成。int* reverse(int* list,int size);第五步:对象指针。定义一个类Cricle,其内有成员函数getName(){return this.name;}定义一个对象指针。Cricle* p;指针访问的成员函数和成员变量使用符号’->'。例如:p->getName();第六步:this指针指向被调用的对象本身。(15)内存分配问题。c++支持动态内存分配,这使得我们能动态的分配持久的内存空间,动态内存的分配使用new操作符。如下:int* p=new int(4);释放内存使用delete。如下: delete p;注意,如果有一个内存是为了一个数组所分配的,为了正确的释放内存,则需在关键字delete和指针间加上符号[].如下:delete [] p;还需要注意的一点事delete只能用于那些指向new操作符创建的内存的指针。例如一下采用delete来删除一个不是由new创建的内存空间就会导致错误。int x=10;int * p=&x;delete p;//出错。(16)析构函数。析构函数是在对象被销毁的时候调用的,创建一个析构函数只需要在方法前面加上符号‘~’。(17)struct学习总结。数组中的数据的类型必须是一样的,但是struct中的的数据类型可以是任意的。定义一个struct。方式如下:struct Address{ string name; string number;.........};//与类的定义基本一致,class Address{ .......}struct的使用方式和class也基本相似。如下使用struct Address。void f( ){Address jd;id.name='xza';}但是例如以上的使用方式并不是常用的。最常用的方式是使用结构指针,如下:void PRitnAddress(Address* p){ cout<<p->name<<endl;}另外需要注意的是:(1)结构体变量可以在定义的时候指定初始值。例如:Address q={beijing,3457890}另外结构体也可以变成结构体数组,例如:Address a[3];它表示是定义了一个数组,数组存放的数据类型是Address,数组名字是a,他的长度为3。(2)c++中struct和类的区别在于struct不能有方法,所有成员是public的。(3)可以在声明struct的时候声明一个struct实例。方法如下:struct Address{ string name; string number;} adr; (18)模板学习。 例如下面的两个函数就可以抽象成模板。 int max(int x,int y){ return x>=y? x,y; } double max(double x,double y){ return x>=y? x,y; }因为这两个函数的功能是一样的,只是传入的参数的数据类型和返回的数据类型不一样而已。抽象成模板如下:template<typename T>//注意这里没有用';'结尾。T max(T x,T y){ return x>=y? x,y;}其中template<typename T>是模板前缀,其中的T是类型参数。[类似于java中的泛型]同时,可能一个模板函数有多个类型参数,则可以这样写,template<typename T1,typename T2,typename T3>另外,需要注意的是模板函数是按值传递的。按引用传递的话可以将模板函数参数设置成为以下例子中所示的格式。例子:template<typename T1> T test(const T& value1,const T& value2){ ....................... }提升知识:模板类模板类例如:template<typename T>calss Address{T name;T getName();}//构造函数template<typename T>Address<T>::Adress(){}template<typename T>T Address<T>::getName(){}需要注意的是模板类不能分开定义和实现。同时每一个具体实现函数之前都需要加上template<typename T>,同时在实现的方法中要在类之后加上<T>,如上两个函数一样。
发表评论 共有条评论
用户名: 密码:
验证码: 匿名发表

图片精选