c++ 基本语法学习
2017-04-27 13:34
465 查看
命名空间
命名空间定义方法
命名空间属性调用
案例
上述案例说明
命名空间引用冲突
命名空间嵌套
输出函数
案例
结构体
如果修饰符含有privat 不能创建
变量引用
二级指针和引用
三目运算符
指针常量和常量指针
实参形参
bool类型
字符串string
函数重载
类 class
简单创建一个类 实例化
析构函数
拷贝构造方法
拷贝函数问题
类静态属性方法初始化
在头文件中声明类和实现
直接在构造函数初始化一些数值
常函数
malloc 和new 的区别
友元函数
运算符重载
未完待续
命名空间定义方法:
命名空间属性调用:
案例:
结果 :
张三
小王
上述案例说明
using namespace std; 再此声明以后的函数使用命名空间std
此声明是用于 cout函数
我们删除上面这句话的看看
解决办法1:
在开头声明using namespace std;
解决办法2:
在函数前添加命名空间
命名空间引用冲突
当你引用了两个命名空间,而两个空间都有age这个属性时,需要手动在函数前指明
命名空间嵌套:
1. cout 函数 位于iostream下
2. 命名空间std
3. 输出方式:
1. std::cout<< 输出内容 ;
- 这样输出不换行
2. std::cout<< 输出内容<< endl;
- 换行输出 ,输出此语句后自动换行
3. std::cout << 输出内容1<<输出内容2 << endl << 输出内容3
- 可以继续拼接输出内容期间可以嵌套endl
案例
结果:
张三
小王小王
张三
如果修饰符含有privat 不能{}创建
输出:
23
爱迪生
输出
24
25
223
223
二级指针和引用
在c++中三目的的结果可以作为 表达式左值
结果:232
c++ 中除非运用指针,或者引用 .不然不会引起实参变化
结果:旧的
输出
输出字符串hello world
输出字符串 长度11
转换为char* hello world
new的对象需要用delete删除堆内存
输出:
构造方法
构造方法
构造方法
析构函数
在对象被回收的时候调用的时候回调的方法
在c++中析构函数为 ~对象名字()
tip:在java中析构函数名字finalize()
输出
析构函数0x1f1f60
拷贝构造方法
应用场景 对象 A = 对象B
此时会回调对象拷贝构造方法
输出:
a
这里学java的同学转c++可能不理解,这里man b = *a; 是将对象a中数值拷贝一份创建一个备份生成,两者互不联系
上面的拷贝拷贝函数没有写 ,是因为系统默认帮我们写了.实际中默认写法如下
拷贝函数问题
上面的代码会在某些编译器运行奔溃:
原因:man类对象中name进行拷贝的时候是直接将指针赋值另一个对象,导致两个对象共用一个,当其中一个销毁的时候,因为name也会被销毁.可是他们共用引起了野指针
解决办法:用深度拷贝
类静态属性方法初始化
案例1.初始化静态变量
可以看到上面报错了.那么到底怎么初始化变量呢?
输出
22
2
案例2静态方法
输出:
静态方法aa
bb方法
在头文件中声明类和实现
先看test.h
再看看实现类
test.cpp
发现用 xxx ();初始化的一个变量的时候无法调用内部方法
解决办法1:
改用new 或者malloc
解决办法2:
创建一个传入参数不是空的构造方法
直接在构造函数初始化一些数值
常函数
malloc 和new 的区别
malloc 创建的对象也会在堆中,但是不会调用class 的构造方法.和构造方法(一般情况下不会,除非你用指针把对象拷贝),其他方式都会调用如 xx(),new xx().
案例1:
输出:无输出
案例2
输出:
指针m保存的地址0x6e1f60
拷贝方法0x61ff18
m2的地址0x61ff18
析构函数0x6e1f60
析构函数0x61ff18
友元函数
当一个类中有私有变量的时候,正常是无法通过xxx.yy去访问的,只能通过函数间接访问.
正常访问私有变量:
友元函数访问私有
案例2
案例1:
案例2
案例3:
命名空间定义方法
命名空间属性调用
案例
上述案例说明
命名空间引用冲突
命名空间嵌套
输出函数
案例
结构体
如果修饰符含有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{ //如果不写访问修饰符默认为 public public: 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"); }
未完待续
相关文章推荐
- 学习SystemC应具备的C++基本语法
- C++学习笔记:异常的基本语法
- C#与C++对比学习1:基本语法区别
- C++学习(一)——基本语法
- C++简单学习(Part1_lecture 1)(介绍、环境设置、基本语法、注释)
- c++基本语法学习2 继承 多态 模板
- [C++学习]基本知识
- [转]C++重读二:C++基本语法(下)
- Dev-C++下基本数据类型学习小结
- 开始着手JAVA了,JAVA基本语法学习笔记
- 初步学习CSS之定义、分类和基本语法
- C#基本语法学习笔记 - LotusCheng's home - CSDNBlog
- c#基本语法学习笔记
- C++重读一:C++基本语法(上)
- C#基本语法学习笔记
- 再读C++ Primer 写了些小例子来熟悉C++基本语法
- [转]C++重读一:C++基本语法(上)
- C++重读二:C++基本语法(下)
- XML学习笔记-XML的基本语法
- 学习:正则表达式的基本语法