c++ 基本语法学习
来源:互联网 发布:约瑟夫环java链表实现 编辑:程序博客网 时间:2024/06/07 08:36
- 命名空间
- 命名空间定义方法
- 命名空间属性调用
- 案例
- 上述案例说明
- 命名空间引用冲突
- 命名空间嵌套
- 输出函数
- 案例
- 结构体
- 如果修饰符含有privat 不能创建
- 变量引用
- 二级指针和引用
- 三目运算符
- 指针常量和常量指针
- 实参形参
- bool类型
- 字符串string
- 函数重载
- 类 class
- 简单创建一个类 实例化
- 析构函数
- 拷贝构造方法
- 拷贝函数问题
- 类静态属性方法初始化
- 在头文件中声明类和实现
- 直接在构造函数初始化一些数值
- 常函数
- malloc 和new 的区别
- 友元函数
- 运算符重载
- 命名空间
- 未完待续
命名空间
前言(转载自百度百科):命名空间是用来组织和重用代码的 。如同名字一样的意思,NameSpace(名字空间),之所以出来这样一个东西,是因为人类可用的单词数太少,并且不同的人写的程序不可能所有的变量都没有重名现象,对于库来说,这个问题尤其严重,如果两个人写的库文件中出现同名的变量或函数(不可避免),使用起来就有问题了。为了解决这个问题,引入了名字空间这个概念,通过使用 namespace xxx;你所使用的库函数或变量就是在该名字空间中定义的,这样一来就不会引起不必要的冲突了
命名空间定义方法:
//定义命名空间namespace XiaoWang{ char * age="小王";}namespace ZhangSan{ char * age="张三";}
命名空间属性调用:
int main(){ //引用命名空间的age变量输出 cout和endl输出方法 类似printf cout<<ZhangSan::age<<endl; std::cout<<XiaoWang::age<<std::endl; return 0;}
案例:
#include<stdio.h>#include<iostream>using namespace std;//定义命名空间namespace XiaoWang{ char * age="小王";}namespace ZhangSan{ char * age="张三";}int main(){ //引用命名空间的age变量输出 cout<<ZhangSan::age<<endl; std::cout<<XiaoWang::age<<std::endl; return 0;}
结果 :
张三
小王
上述案例说明
using namespace std; 再此声明以后的函数使用命名空间std
此声明是用于 cout函数
我们删除上面这句话的看看解决办法1:
在开头声明using namespace std;解决办法2:
在函数前添加命名空间
int main(){ //引用命名空间的age变量输出 std::cout<<ZhangSan::age<<std::endl; std::cout<<XiaoWang::age<<std::endl; return 0;}
命名空间引用冲突
当你引用了两个命名空间,而两个空间都有age这个属性时,需要手动在函数前指明
命名空间嵌套:
/* * test.cpp * * Created on: 2017��4��25�� * Author: FMY */#include<stdio.h>#include<iostream>using namespace std ;//定义命名空间namespace A{namespace B{ char * test ="测试";}}int main(){ cout<<A::B::test<<endl; return 0;}
输出函数
c语言输出函数printf 对应c++的cout函数
1. cout 函数 位于iostream下
2. 命名空间std
3. 输出方式:
1. std::cout<< 输出内容 ;
- 这样输出不换行
2. std::cout<< 输出内容<< endl;
- 换行输出 ,输出此语句后自动换行
3. std::cout << 输出内容1<<输出内容2 << endl << 输出内容3
- 可以继续拼接输出内容期间可以嵌套endl
案例
#include<stdio.h>#include<iostream>using namespace std ;//定义命名空间namespace XiaoWang{ char * age="小王";}namespace ZhangSan{ char * age="张三";}int main(){ using namespace ZhangSan; //以后的代码出现age都是ZhangSan的 cout<<age<<endl; //除非这样下 cout<<XiaoWang::age; cout<<XiaoWang::age<<endl<<age; return 0;}
结果:
张三
小王小王
张三
结构体
#include<stdio.h>#include<iostream>using namespace std ;struct person{//如果不写访问修饰符默认为 publicpublic: char name [20]; int age;public: int weight; void (*eat)(char * food);};void eat2(char *food){ cout<<"我在吃"<<food<<endl;}int main(){ //不需要写 struct 并且增加访问符号 person p{"asd",1,1,eat2}; p.eat("asd"); return 0;}
如果修饰符含有privat 不能{}创建
变量引用
前言:就是某一变量(目标)的一个别名,对引用的操作与对变量直接操作完全一样。(次句话转自某博文)
#include<iostream>using namespace std;struct MyStruct{ char *name;};int main(){ int a = 1; int b = 27; //给a变量取别名c //修改c变量会直接修改a变量 int &c = a; //此时a也会变成23 c = 23; MyStruct p1{ "阿斯顿" }; //给p取别名 MyStruct &p2 = p1; //此时 p.name也会变 p2.name = "爱迪生"; cout << a<<endl; cout << p2.name; getchar(); return 0;}
输出:
23
爱迪生
#include<iostream>using namespace std;struct MyStruct{ char *name;};//返回同一个引用 由于是static 修饰 所以访问的是同一个int & test(){ //静态修饰的只会第一次调用的时候执行a = 23 static int a = 23; return ++a;}//每次从栈返回 一个引用 不推荐 int& test2(){ int a = 222; return ++a;}int main(){ cout << test() << endl; cout << test() << endl; int c = test2(); cout << test2() << endl; cout << test2() << endl; getchar(); return 0;}
输出
24
25
223
223
二级指针和引用
#include<stdio.h>#include<iostream>#include<string.h>#include<stdlib.h>using namespace std ;struct Man{ char*name;};int main(){ Man *m1 = (Man*) calloc(sizeof(Man),1); m1->name ="你好兄弟"; Man ** m2 = (Man**) calloc(sizeof(Man*),1);; m2 = &m1; cout<<"一级指针"<<m1->name<<endl; cout<<"二级指针"<<(*m2)->name<<endl; //-----------------引用和二级指针----------------------- Man *aaa = (Man*) calloc(sizeof(Man),1); //以下这种方法是错误,因为我们说过引用是取别名 ,你没有原本的名字变量 怎么取别名? //Man &aaa = (Man*) calloc(sizeof(Man),1); Man* &mm1 = aaa; mm1->name = "嘿嘿"; cout<<"二级引用"<<mm1->name<<endl; return 0;}
三目运算符
前言:
在c++中三目的的结果可以作为 表达式左值
#include<stdio.h>#include<iostream>#include<string.h>using namespace std ;int main(){ int a = 1; int b = 2; *((a>b)?&a:&b) = 232; cout<<b<<endl; return 0;}
结果:232
指针常量和常量指针
实参形参
在 java方法中传入一个对象 ,在方法中修改对象会直接影响实参 .
c++ 中除非运用指针,或者引用 .不然不会引起实参变化
/* * test.cpp * * Created on: 2017��4��25�� * Author: FMY */#include<stdio.h>#include<iostream>#include<string.h>using namespace std ;struct Man{ char *name;};//传入的时候把实参拷贝一份在方法栈区void test( Man p){ //此时修改并不影响调用方法的实参 p.name ="修改";}int main(){ Man man {"旧的"}; //传入的时候把实参拷贝一份在方法栈区 test(man); cout<<man.name<<endl; return 0;}
结果:旧的
bool类型
/* * test.cpp * * Created on: 2017��4��25�� * Author: FMY */#include<stdio.h>#include<iostream>#include<string.h>using namespace std ;int main(){ bool flag = true;// bool flag = 1;//这里也是可以赋值数值类型的 if(flag){ cout<<"真的"<<endl; }else{ cout<<"假的"<<endl; } cout<<"bool所占用字节数"<<sizeof(bool)<<endl; return 0;}
结果:真的bool所占用字节数1
字符串string
因为string的使用和java差不多所以这里不打算说太多
#include<stdio.h>#include<iostream>#include<string.h>#include<stdlib.h>using namespace std ;int main(){ string testString = "hello world"; cout<<"输出字符串"<<testString<<endl; cout<<"输出字符串 长度"<<testString.length()<<endl; //转化为char* const char * convertChar = testString.c_str(); cout<<"转换为char* "<< convertChar<<endl; return 0;}
输出
输出字符串hello world
输出字符串 长度11
转换为char* hello world
函数重载
我们在java的时候调用方法是支持重载的,可以根据实参传入的类型和个数位置不同确定调用哪一个方法
#include<stdio.h>#include<iostream>#include<string.h>#include<stdlib.h>using namespace std ;void my(char * name){ cout<<"my(char * name) ----"<<name<<endl;}void my(int name){ cout<<"my(int * name) ----"<<name<<endl;}int main(){ //根据传入的参数类型和个数确定调用哪个类型 my("sd"); my(1); return 0;}
类 class
简单创建一个类 实例化
new的对象需要用delete删除堆内存
#include<stdio.h>#include<iostream>#include<string.h>#include<stdlib.h>#include <stdio.h>#include <stdarg.h>using namespace std ;class man{public : char * name ; //构造方法 man(char *name){ cout<<"构造方法"<<endl; this->name =name; }};int main(){ //这种创建方式会 在栈中创建 ,对象可控性不强 man a("Asd"); //和上面的一样 man b = man ("Asd"); //如果使用new的方式 需要 delete删除,因为new是从堆创建的所以和malloc man * c = new man ("new 创建"); //从堆中删除c delete c; return 0;}
输出:
构造方法
构造方法
构造方法
析构函数
在对象被回收的时候调用的时候回调的方法
在c++中析构函数为 ~对象名字()
tip:在java中析构函数名字finalize()
#include<stdio.h> #include<iostream> #include<string.h> #include<stdlib.h> #include <stdio.h> #include <stdarg.h> using namespace std ; class man{ public : char * name ; ~man(){ cout<<"析构函数" <<this<<endl; } }; int main(){ man *a=new man (); delete a; return 0; }
输出
析构函数0x1f1f60
拷贝构造方法
应用场景 对象 A = 对象B
此时会回调对象拷贝构造方法
#include<stdio.h>#include<iostream>#include<string.h>#include<stdlib.h>#include <stdio.h>#include <stdarg.h>using namespace std ;class man{public : char * name ; man(char * name){ this->name = name; }};int main(){ man * a=new man ("a"); man b = *a; b.name= "b"; cout<<a->name<<endl; return 0;}
输出:
a
这里学java的同学转c++可能不理解,这里man b = *a; 是将对象a中数值拷贝一份创建一个备份生成,两者互不联系
上面的拷贝拷贝函数没有写 ,是因为系统默认帮我们写了.实际中默认写法如下
#include<stdio.h>#include<iostream>#include<string.h>#include<stdlib.h>#include <stdio.h>#include <stdarg.h>using namespace std ;class man{public : char * name ; man(char * name){ this->name = name; } //默认拷贝方法 ----值拷贝 浅拷贝 man(const man& p){ this->name = p.name; }};int main(){ man * a=new man ("a"); man b = *a; b.name= "b"; cout<<a->name<<endl; return 0;}
拷贝函数问题
#define _CRT_SECURE_NO_WARNINGS#include<stdio.h>#include<iostream>#include<string.h>#include<stdlib.h>#include <stdio.h>#include <stdarg.h>using namespace std ;class Man{public: char *name;public: Man(char *name){ this->name = (char*)malloc(100); strcpy(this->name,name); cout << "构造函数" << endl; } ~Man(){ //释放内存 free(this->name); cout << "析构函数" << endl; } void myprint(){ cout << name << endl; }};void func(){ Man m1((char*)"fmy"); Man m2 = m1; strcpy(m1.name,"asd"); m2.myprint();}int main(){ func(); return 0;}
上面的代码会在某些编译器运行奔溃:
原因:man类对象中name进行拷贝的时候是直接将指针赋值另一个对象,导致两个对象共用一个,当其中一个销毁的时候,因为name也会被销毁.可是他们共用引起了野指针
解决办法:用深度拷贝
#define _CRT_SECURE_NO_WARNINGS#include<stdio.h>#include<iostream>#include<string.h>#include<stdlib.h>#include <stdio.h>#include <stdarg.h>using namespace std;class Man{public: char *name;public: Man(char *name){ this->name = (char*)malloc(100); strcpy(this->name, name); cout << "构造函数" << endl; } ~Man(){ //释放内存 free(this->name); cout << "析构函数" << endl; } Man(const Man& m){ this->name = (char *)malloc(sizeof(char)* 111); strcpy(this->name, m.name); } void myprint(){ cout << name << endl; }};void func(){ Man m1((char*)"fmy"); Man m2 = m1; strcpy(m1.name, "asd"); m2.myprint();}int main(){ func(); getchar(); return 0;}
类静态属性方法初始化
- 案例1.初始化静态变量
可以看到上面报错了.那么到底怎么初始化变量呢?
#define _CRT_SECURE_NO_WARNINGS#include<stdio.h>#include<iostream>#include<string.h>#include<stdlib.h>#include <stdio.h>#include <stdarg.h>using namespace std ;class Man{public : static int a ;};int Man::a =22;int main(){ cout<<Man::a<<endl; Man::a =2; cout<<Man::a<<endl; Man s(); return 0;}
输出
22
2
- 案例2静态方法
#define _CRT_SECURE_NO_WARNINGS#include<stdio.h>#include<iostream>#include<string.h>#include<stdlib.h>#include <stdio.h>#include <stdarg.h>using namespace std ;class Man{public : static void aa(){ cout<<"静态方法aa"<<endl; } static void bb();};void Man::bb(){ cout<<"bb方法"<<endl;}int main(){ Man::aa(); Man::bb(); return 0;}
输出:
静态方法aa
bb方法
在头文件中声明类和实现
先看test.h
class man{public: char *name; void eat();};
再看看实现类
test.cpp
发现用 xxx ();初始化的一个变量的时候无法调用内部方法
- 解决办法1:
改用new 或者malloc
int main(){ man* m =new man(); m->eat(); m->name = "你好吗?"; getchar(); return 0;}
- 解决办法2:
创建一个传入参数不是空的构造方法
class man{public: char *name; void eat(); man(int a){ }};
#include<iostream>#include"test.h"using namespace std;void man::eat(){ cout << "asd" << endl;};int main(){ man a(1); a.name = "asd"; getchar(); return 0;}
直接在构造函数初始化一些数值
常函数
malloc 和new 的区别
malloc 创建的对象也会在堆中,但是不会调用class 的构造方法.和构造方法(一般情况下不会,除非你用指针把对象拷贝),其他方式都会调用如 xx(),new xx().
案例1:
class man{public : char * name ; //构造方法 man(char *name){ cout<<"构造方法被调用咯 传入的name===" <<name<<endl; this->name =name; } man(const man& m){ cout<<"拷贝方法"<<endl; this->name = m.name; } ~man(){ cout<<"析构函数"<<endl; }};int main(){ man *m = (man* ) malloc(sizeof(man)); free(m); return 0;}
输出:无输出
案例2
#include<stdio.h> #include<iostream> #include<string.h> #include<stdlib.h> #include <stdio.h> #include <stdarg.h> using namespace std ; class man{ public : char * name ; //构造方法 man(char *name){ cout<<"构造方法被调用咯 传入的name===" <<name<<endl; this->name =name; } man(const man& m){ cout<<"拷贝方法" <<this<<endl; this->name = m.name; } ~man(){ cout<<"析构函数" <<this<<endl; } }; int main(){ man *m = (man* ) malloc(sizeof(man)); cout<<"指针m保存的地址"<<m<<endl; m->name = "嘿嘿"; //将指针保存的内容拷贝到别处man对象上 ,触发拷贝发生 在对象回收后触发析构函数 在栈区创建的对象m2 man m2 = *m; cout<<"m2的地址"<<&m2<<endl; //用此方法可以回收 m内存 并且回调析构函数 delete m; return 0; }
输出:
指针m保存的地址0x6e1f60
拷贝方法0x61ff18
m2的地址0x61ff18
析构函数0x6e1f60
析构函数0x61ff18
友元函数
当一个类中有私有变量的时候,正常是无法通过xxx.yy去访问的,只能通过函数间接访问.
正常访问私有变量:
友元函数访问私有
#define _CRT_SECURE_NO_WARNINGS#include<stdio.h>#include<iostream>#include<string.h>#include<stdlib.h>#include <stdio.h>#include <stdarg.h>using namespace std ;#include"test.h"class woman {friend void accessmy(woman *p);public: int age; char *name;private: //私有变量 int weight; void eat(){ cout<<"私有方法eat"<<endl; }};void accessmy(woman *p){ cout<<"访问"<<p->weight<<endl;}int main(){ woman* m = new woman(); accessmy(m); return 0;}
- 案例2
#define _CRT_SECURE_NO_WARNINGS#include<stdio.h>#include<iostream>#include<string.h>#include<stdlib.h>#include <stdio.h>#include <stdarg.h>using namespace std ;#include"test.h"class woman {friend class B;public: int age; char *name;private: //私有变量 int weight; void eat(){ cout<<"私有方法eat"<<endl; }};class B{public : void accessmy(){ //随便访问 w.weight =30; }private: woman w;};
运算符重载
我们在使用java的String类型可以用”+”号拼接两个字符串,c++当然也可以.在我们一开始使用cout函数”<<”符号的时候 大家有没有想过他们是怎么做到的?
案例1:
#define _CRT_SECURE_NO_WARNINGS#include<stdio.h>#include<iostream>#include<string.h>#include<stdlib.h>#include <stdio.h>#include <stdarg.h>using namespace std ;#include"test.h"class Point{ public: int x; int y; Point(int x,int y):x(x),y(y){ }};Point operator+(const Point &p1, const Point & p2 ){ return Point (p1.x+p2.x,p1.y+p2.y);}int main(){ Point p1(1,3); Point p2(2,4); Point p3 = p1+p2; cout<<"("<<p3.x<<","<<p3.y<<")"<<endl; return 0;}
案例2
#define _CRT_SECURE_NO_WARNINGS#include<stdio.h>#include<iostream>#include<string.h>#include<stdlib.h>#include <stdio.h>#include <stdarg.h>using namespace std ;#include"test.h"class Point{ public: int x; int y; Point(int x,int y):x(x),y(y){ } Point operator+( Point & p2 ){ return Point (this->x+p2.x,this->y+p2.y); }};int main(){ Point p1(1,3); Point p2(2,4); Point p3 = p1+p2; cout<<"("<<p3.x<<","<<p3.y<<")"<<endl; return 0;}
案例3:
//当属性私有时,通过友元函数完成运算符重载class Point{ friend Point operator+(Point &p1, Point &p2);private: int x; int y;public: Point(int x = 0, int y = 0){ this->x = x; this->y = y; } void myprint(){ cout << x << "," << y << endl; }};Point operator+(Point &p1, Point &p2){ Point t(p1.x + p2.x, p1.y + p2.y); return t;}void main(){ Point p1(1, 3); Point p2(2, 4); //运算符的重载,本质还是函数调用 //p1.operator+(p2) Point p3 = p1 + p2; system("pause");}
未完待续
- C语言学习-基本语法
- C语言学习:基本语法
- Object-C学习之三:Object-C基本语法之一
- C语言基本语法
- Object-c基本语法
- Objective-c基本语法
- Objective C基本语法
- Objective-C基本语法
- C 基本语法
- C#-基本语法
- C 基本语法
- 【C#】 基本语法
- C语言学习笔记(一) -基本语法 Basic Grammar
- 【C语言学习笔记】基础语法及基本运算
- 【Objective-C学习笔记】基本语法、类与对象
- 学习笔记1—C语言的基本语法
- c语言学习笔记_2基本词法语法规则
- JSP基本语法学习
- 数学模型之解析解、闭合解、数值解
- JAVA递归算法实例小结
- Java 数组第二大的值
- CentOS7.0环境下,为MariaDB设置中文
- 移动端开发时,让字体小于12px的方法
- c++ 基本语法学习
- 51nod 2级算法题-1126
- Unity脚本事件执行
- 利用MyBatis Generator自动创建代码
- 如何使用String的replaceAll方法替换字符串中的反斜杠“\”或增加反斜杠“\”
- nodejs express框架的快速安装
- Java集成kettle调用trans文件
- C++中将string类型转换为int, float, double互转
- 对称密钥与非对称密钥