c++概述
C++是面向对象的编程,同时也是一种泛型编程。
面向过程是一种以过程为中心的编程思想,通过分析出解决问题所需要的步骤,然后用函数把这些步骤一步一步实现,使用的时候一个一个依次调用就可以了。面向过程编程思想的核心:功能分解,自顶向下,逐层细化(程序=数据结构+算法)。面向过程的编程语言存在的主要缺点是不符合人的思维习惯,而是要用计算机的思维方式去处理问题,而且面向过程编程语言重用性低,维护困难。
面向对象的编程(Object-Oriented Programming)简称OOP技术,常常使用许多代码模块,每个模块都只提供特定的功能,它们是彼此独立的,这样就增大了代码重用的几率,更加有利于软件的开发、维护和升级。在面向对象的开发过程中,算法与数据结构倍看作是一个整体,称为对象梦想是世界中任何类的对象都具有一定的属性和操作,也总能用数据结构与算法两者合一地描述,所以可以用下面的等式来定义对象和程序:对象=算法+数据结构 程序=对象+对象+…
面向对象编程思想的核心:应对变化,提高复用。
c++的三大特性
封装:把客观的事物封装成抽象的类,并且类可以把自己的数据和方法只让可信的类或者对象操作,对不可信的进行信息隐藏。类将成员变量和成员函数封装在类的内部,根据需要设置访问权限,通过成员函数管理内部状态。数据->成员数据,方法->成员函数。
继承:继承所表达的是类之间相关的关系,这种关系使得对象可以继承另外一类对象的特征和能力。继承的作用在于,避免公用代码的重复开发,减少代码和数据冗余。
多态:多态性可以简单地概括为“一个接口,多种方法”,字面意思为多种形态。程序在运行时才决定调用的的函数,它是面向对象编程领域的核心概念。
c++对c的扩展
1.作用域运算::
通常情况下,如果有两个同名变量,一个是全局变量,另一个是局部变量,那么局部变量在其作用域内具有较高的优先权,它将屏蔽全局变量。作用域可以解决局部变量和全局变量的重名问题。
eg.
// 作用域举例
int a=10;
void test(){
//局部变量
int a=20;
//全局a被隐藏
cout<<"a="<<a<<endl;//a=10
cout<<"a="<<::a<<endl;//a=20
}
2.名字控制
创建名字是程序设计过程中一项最基本的活动,当一个项目很大时,它不可避免的包含大量的名字。c++允许我们对名字的产生和名字的可见进行控制。之前在学习c语言可以通过static关键字来使名字在本编译单元内可见,在c++中我们将通过一定通过命名空间来控制对名字的访问。
2.1 命名空间(namespace)
在c++中,名称(name)可以是符号常量、变量、函数、结构、枚举、类和对象等等。工程越大,名称互相冲突的可能性越大。在使用不同厂商的类库时,也可能导致名称冲突。为了避免,在大规模程序设计中标识符命名发生冲突,标准c++引入关键字namespace,可以更好地控制标识符的作用域。
2.2 定义
// 命名空间
namespace A{
int data_1 = 10;
}
namespace B{
int data_1 = 20;
}
void test(){
cout<<"data_1"<<A::data_1<<endl;
cout<<"datd_1"<<B::data_1<<endl;
}
2.3 注意
①命名空间只能在全局进行定义
②命名空间可以嵌套命名空间,A::B::变量
③命名空间是开放的,可以随时把新的成员加入已有的命名空间中
// ③
namespace A{
int a = 10;
}
...//1000行之后
namespace A{
int b = 9;
}//此时,A不算重新定义,而是表示空间A中新增了成员b,合并
2.4 声明和实现可以分离
// 分离
namespace B{
int a = 10;
int get_a(void);
}
int C::get_a(void){
return a;
}//命名空间的方法可以在空间之外定义,但是需要在方法之前加上空间名称
2.5 无命名空间
意味着明明空间中的标识符只能在本文件中访问,相当于给这个标识符加上了static,使得其可以作为内部连接。
2.6 命名空间别名
// An highlighted block
namespace verylongname{
int a = 10;
void func(){ cout<<"hello namspace"<<endl'}
}
void test(){
namespace shortName = verylongname;//赋值运算符
cout << "verylongname::a:"<<shortname::a<<endl;
verylongname::func();
shortName::func();
}
2.7 using是修饰 命令空间 内部的某些数据和方法
// An highlighted block
namespace D{
int a =10;
}
void test04(){
using D::a;//此处的a来自D命名空间
//但是不排除会出现同名情况
int a = 20;//此处又定义了一个a
cout<<"a="<<a<<endl;//此处将报错,不知道访问哪个a
}
2.8 using声明碰到函数重载
// 体现了C++的多态性
namespace A{
void func(){}
void func(int x){}
void func(int x, int y){}
}
void test(){
using A::func();
func();
func(10);
func(10,20);
}
如果命名空间包含一组相同名字重载的函数,using声明就声明可这个重载函数的所有集合。
2.9 using是修饰整个命名空间
// An highlighted block
namespace D {
int a = 10;
int b = 20;
int c = 30;
}
void test(){
using D::a;
using D::b;
using D::c;//太麻烦了,为了避免麻烦,采用下面方式直接声明整个命名空间
using namespace D;//此处需要加namespace,强调命名空间,和2.7强调命名空间内的数据和方法不同,此处先查看当前普通变量a,如果没有,再查看命名空间中有没有a
}
全局变量增强
// 告诉用户严谨定义
int a = 10;//赋值,当做定义
int a;//没有赋值,当做声明
int main(){
printf("a:%d\n",a);
return 0;
}//此代码在c++下编译失败,在c下编译通过,原因在于c++编译要求更严谨,这里a既定义又声明,不符合编译标准。
类型增强
c++中所有的变量和函数都必须有类型。在C语言中,函数声明中没有说明其中的参数是什么类型,则可以是任意类型;没有写参数,代表可以传任意类型的实参。BUT,在c++中不行,如果函数没有参数,那么调用的时候不能传实参。
更严格的类型转换
在c++中要养成一种习惯,两个变量类型应该相同,如果两个变量类型不同怎么办,那就强制类型转换。在c++中多用引用,而不用指针。
在c++,不同类型的变量一般是不能直接赋值的,需要相应的强转。
结构体的增强
c中定义结构体变量需要加上struct关键字,c++不需要。c中的结构体只能定义成员变量,不能定义成员函数。c++既可以定义成员变量,也可以定义成员函数。(结构体中的函数默认是共有类型)
// 1.结构体中既可以定义成变量,也可以定义成员函数
struct Student{
string mName;
int mAge;
void setName(string name){ mName = name;}
void setAge(int age){mAge = age;}
void showStudent(){
cout<<"Name:"<<mName<<"Age:"<<mAge<<endl;
}
};
//2.c++中定义结构体变量不需要加struct关键字
void test01(){
Student student;
student.setName("John");
student.setAge(20);
student.showStuent();
}
新增bool类型
标准c++的bool类型有两种内建的常量true(转化为整数1)和false(转化为整数0)表示状态。这三个名字都是关键字。bool类型只有两个值,true(1值)、false(0值),bool类型占1个字节大小,给bool类型赋值时,非0值会自动转换为true(1),0值会自动转换false(0)
void test(){
cout<<sizeof(false)<<endl;//显示bool类型占的字节大小
bool flag = true;//c语言中没有这种类型
flag = 100;//给bool类型赋值时,会自动进行转换
}
三目运算符
c语言中的三目运算符a>b?a:b,返回的是a或者b的值。
c++中三目运算符是a或b的引用(a或b的变量名)
在程序执行过程中
a=10;b=20;
(a>b?a:b) = 100;c语言中会报错,c++中不会报错。
c++ code
#include <iostream> //标准输入输出流 i - input 输入 o - output 输出 stream 流 相当于 stdio.h
using namespace std; //使用 标准 命名空间
//#include <time.h>
//#include <ctime>
//
//#include <math.h>
//#include <cmath>
//程序入口函数
int main()
{
// cout 标准输出流对象
// << 左移 在C++下有了新的寓意 用于在cout后拼接输出的内容
// endl --- end line 刷新缓冲区 并且换行
cout << "hello world" << endl;
system("pause"); //阻塞
return EXIT_SUCCESS; //返回正常退出
}
双冒号作用运算符
#include <iostream> //标准输入输出流 i - input 输入 o - output 输出 stream 流 相当于 stdio.h
using namespace std; //使用 标准 命名空间
//#include <time.h>
//#include <ctime>
//
//#include <math.h>
//#include <cmath>
//程序入口函数
int main()
{
// cout 标准输出流对象
// << 左移 在C++下有了新的寓意 用于在cout后拼接输出的内容
// endl --- end line 刷新缓冲区 并且换行
cout << "hello world" << endl;
system("pause"); //阻塞
return EXIT_SUCCESS; //返回正常退出
}
namespace用法
#include<iostream>
using namespace std;
namespace KingGlory{
int sunwukongId =1;
}
namespace King{
int sunwukongId =19;
}
int main(){
using namespace KingGlory;
using namespace King;
cout<<King::sunwukongId<<endl;
int aaa =23;
cout<<"time..."<<aaa<<endl;
}
引用
#include <iostream>
using namespace std;
int main(){
int a =10;
int &b= a;
cout<<a<<b<<endl;
}
指针和引用
#include <iostream>
using namespace std;
int main(){
//int &ref = 10;
const int &ref = 10; // 加了const之后, 相当于写成 int temp = 10; const int &ref = temp;
int *p = (int *)&ref;
*p = 10000;
cout << ref << endl;
}