文章目录
基本的输入/输出
C语言的scanf == cin
- 输入: cin
- 输出:cout
getchar()函数 用于接收空格、teb、enter等字符
#include <iostream> // 头文件标准输出输入流
#include <string> // 头文件字符串
using namespace std; // 命名空间
int main() // 主函数,程序从这里开始执行
{
string str;
cout << "hello world!" << endl;
cin >> str;
cout << str << endl;
sleep(5);
return 0;
}
常用的头文件
-
<iostream> 标准的输入输出流
-
<fstream> 标准的文件流
-
<string> 标准的字符串处理函数
-
<cmath> 标准的数学函数
命名空间
命名空间(namespace):是一种将程序库名称封装起来的方法,它提高了程序的性能和可靠性。可消除同名引起的冲突
标准程序库的命名空间 using namespace std;
引入其他命名空间标识符为:
命名空间名::标识符名
类型转换
- 强制类型转换
static_cast <类型名> 表达式 , static_cast可以省略
ontInt2 = int(oneDouble); //新形式
ontInt2 = (int)oneDouble; //旧形式 - 自动类型转换小的类型自动转换为大的类型
double>float>int>char - 去常量性
const_cast<类型名>表达式
用于去除指针与引用的常量性,但不能去除变量的常量性。 - char c=‘c’ 会根据ascii码转换成整型。
函数
1、函数参数的默认值
默认参数就是不要求程序员设定该参数,而由编译器在需要时给该参数赋默认值。当程序员需要传递特殊值时,必须显式地指明。
默认参数是在函数原型中说明的,默认参数可以多于1个,但必须放在参数序列的后部。
在函数原型中,可以省略形参名字,而只给出它的类型及默认值。
void defaultvalue1(int = 2 , double = 3.0);
void defaultvalue1(int a , double b = 3.0);
1.1 void 数据类型
void是空的意思,一般用来表示无参数或者无返回。
void 字面意思是“无类型”,void* 无类型指针,无类型指针可以指向任何类型的数据。
void 定义变量是没有任何意义的,当你定义 void a,编译器会报错。
void 真正应用的两个方面:
对函数反回的限定;
对函数参数的限定;
2、引用与函数参数
(1)引用的定义
类型名 &引用名 = 同类型的某变量名;
int oneInt = 9 ;
int &aname = oneInt; //声明引用
引用相当于给变量取了个别名,aname和oneInt占用同一内存地址,
变量oneInt必须已进行初始化,不能声明引用的引用。
const int &cname = ontInt ; //常引用
不能通过常引用去修改其引用的变量
(2)引用在函数中的使用
C++中函数调用时参数的传递方式:传值、传引用
传值:形参是实参的副本,形参的改变不会影响实参
传引用:形参的改变,意味着实参的改变
传引用是传递对象的首地址。
变量、指针、引用都可以作为赋值语句的左值。
示例:
#include <iostream>
#include <string>
using namespace std;
int main()
{
int oneInt = 1;
int &ref = oneInt;
const int &refc = oneInt;
ref = 2;
cout << "oneInt="<< oneInt<<"___"<<"ref="<<ref<<endl;
cout << "refc="<< refc<<endl;
oneInt = 3;
cout << "ref="<< ref<<endl;
cout << "refc="<< refc<<endl;
int &ref2 = ref;
cout << "ref2="<< ref2<<endl;
sleep(10);
return 0;
}
3、内联函数 inline
避免频繁调用与返回,C++引入内联函数,以空间消耗节省时间开销
内联函数适合于只有几条语句的小函数,降低函数调用的开销
如果函数体中有循环或switch语句,通常不定义为内联函数
定义内联函数的格式为:
inline 返回值类型 函数名(形参表){
函数体
}
#include<iostream>
#include<string>
using namespace std;
inline int qwq(int &a){
int c=111;
return c+a;
}
int main (){
int a=100, *p = &a;
cout <<"string:"<<to_string(qwq(a))<<endl;
sleep(10);
}
4、函数重载
函数重载可以使一个函数名具有多种功能,即具有“多种形态”,
这种特性称为多态性。
C++的多态性又被直观地称为“一个名字,多个函数”。源代码只指
明函数调用,而不说明具体调用哪个函数。编译器的这种连接方式
称为动态联编或迟后联编。在动态联编中,直到程序运行才能确定
调用哪个函数。函数重载机制,减少了命名空间的浪费。
重载的两种情况:参数个数不同,或参数对应类型不同
返回类型,引用参数都不能区分重载
#include<iostream>
#include<string>
using namespace std;
int qwq(int x,int y){
int c=111;
return c+x+y;
}
int qwq(float x,float y){
int c=111;
return c+x+y;
}
int qwq(double x,double y){
int c=111;
return c+x+y;
}
int qwq(int x,int y,int z){
int c=111;
return c+x+y+z;
}
int main (){
int a=1,b=2,c=3;
cout <<"return:"<<to_string(qwq(a,b,c))<<endl;
sleep(10);
}
动态内存分配与string字符串
1、 用new运算符的使用
new运算符分配的内存空间,可为数组和指
针分配内存空间。
·指针:
指针是一个变量,其值为另一个变量的地址,即,内存位置的直接地址。
#include<iostream>
#include<string>
using namespace std;
int main(){
int a=1, *p=&a;
cout<<a<<"__"<<p<<endl;
sleep(5);
}
/*
p ==>内存地址
*p ==> 指针变量的值 如果是数组只会显示第一个元素,如果没有分配元素,没有存入数据则为八位随机数字(我也不知道是什么)。
*/
使用关键字new实现动态内存分配
T *p = new T; //分配大小为sizeof(T)字节的内存空间
T *p = new T[N]; //分配一个任意大小的数组,N为数组元素个数
使用完毕使用delete释放空间
delete 指针; delete []指针;//释放数组
#include<iostream>
#include<string>
using namespace std;
int main(){
int *p; // 定义指针变量p
p = new int; // 给动态分配四个字节大小的内存空间
*p = 100; // 也可以p[0] = 100; 在空间里存入数值100
cout << p<< endl<< *p<<endl;
cout<<"**********"<<endl;
int *pArray;
int i = 5;
pArray = new int[i*20];
pArray[1] = 1;
pArray[99] = 99;
cout<<*pArray<<"___"<<pArray<<"___"<<pArray[0]<<"___"<<pArray[1]<<"___"<<pArray[99]<<endl;
delete p; // 释放空间
delete []pArray;
// delete []pArray,p;
sleep(10);
}
2、用string对象处理字符串
C++提供了string类型,string是一个类,这个类型的变量称为
“string对象”,使用string对象时需要包含头文件
#include<string>
(1)声明string对象与初始化
string str1;
string city=“Beijing”;
string str2=city;
不论字符串长度如何,string对象的大小都是sizeof(string)
字符数组的定义:string citys[]={“Beijing”,”Shanghai”};
(2)string对象的操作
string对象可以相互赋值
string s1,s2=“OK”;
s1 = “China”;
s2 = s1;
string对象之间的比较可以< <= != == 等进行比较,大小按
字母顺序,区别大小写, “+”号作为字符串的连接符号。
(3)string类中常用成员函数
const char * c_str() const; 返回一个指向字符串的指针
int size() const ; 返回当前字符串的大小
int length() const ; 返回当前字符串的长度
bool empty() const; 判断当前字符串是否为空
size_type find(const char * str,size_type index); 返回str在
字符串中第一次出现的位置(从index开始查找)
string &insert(int p,const string &s);在p位置插入字符串s
string &append(const char *s); 将字符串连接到当前字符串结尾
string substr(int pos=0,int n=npos);返回从pos开始的子串
#include<iostream>
#include<string>
using namespace std;
main(){
string str;
str = "hello world!";
cout<<str<<endl;
cout<<str.size()<<endl;
cout<<str.length()<<endl;
cout<<str.empty()<<endl;
cout<<str.find("o",0)<<endl;
cout<<str.insert(5,",")<<endl;
cout<<str.append("^_^")<<endl;
cout<<str.substr(7)<<endl;
sleep(8);
}
C++程序的结构
1、主程序main
(1)C++程序以.cpp为文件扩展名,文件中包含若干类和函数。程序中有且仅有一个主函数main(),这是程序执行的的总入口。
(2)主函数中可以调用其他函数,但其他函数不可以调用主函数。
2、C++的注释风格
(1)多行注释:从/** 开始,到 */结束,这之间的所有内容都为注释
(2)单行注释:从 //直到行尾,都是注释
面向对象的基本概念
理解结构化程序设计,面向对象程序设计:类与对象、抽象、封装、继承、多态的基本概念;能够定义类的成员变量和成员函数;掌握构造函数和析构函数、复制构造函数的概念与定义;理解对象的概念、掌握通过对象访问类成员的方法。
一 、结构化程序设计
- 结构化程序设计与叫面向过程的设计方法,思想:自顶向下、逐步求精、模块化,把大问题分解为小任务,用函数来完成,将逻辑功能相关独立的程序设计成函数。
程序=数据结构+算法
- 结构化程序设计的局限性:对变量进行的操作函数可能散布在程序的各处,如果变量类型有所变化,则相关的函数都需要修改,程序的维护开销较大。程序规划庞大时,会变得难以理解、难以扩充、难以查错和难以复用。
- 结构化程序设计三种基本程序结构:顺序、选择、循环
二、面向对象程序设计的概念和特点
- 面向对象的程序设计方式更接近于人们看待的真实世界
- 对象具有两个特性:状态(属性)、行为(操作),在程序中属性用变量表示,操作用函数来实现。
- 类:来对现实客观事实的抽象,找出同一类对象的共同属性(静态特征)和行为(动态特征)。
- 对象是类的实例,类是对象的一个抽象。
- 面向对象的程序设计有4个基本特点:抽象、封装、继承、多态
- 封装、继承、多态
- 封装:将对象的属性及实现细节结合在一起,构成独立的实体。封装可以将对象的部分属性和函数隐藏起来,对外不可见,将另外一部分对外可见,提供操作的接口。
- 继承:在编写新的类时,以现有的类为基础,使得新类从现有的类派生出来,达到代码扩充和复用的目的。原来的类是基类(父类、超类),新类是派生类(子类),继承体现了类的层次关系
- 多态:指不同种类的对象具有名称相同的行为,具体行为的实现方式有所不同。在一个类或多个类中,可以让多个方法使用同一个名字。
三 、类的初步知识
类的定义:
- 面向对象的方法中类,是对具有相同属性的和行为的同一类对象的抽象描述,其内部包括属性(本类的成员变量)和行为(本类的成员函数)两个部分。类是用户自定义的数据类型。格式为
class 类名{
访问范围说明符号;
成员变量;
访问范围说明符号;
成员函数声明;
}
- 访问范围说明符有三种: public(公有)、private(私有)、protected(保护)
- 类中的成员变量不能再声明时进行初始化。成员函数定义在类体内部,则默认为内敛函数,也可以在类体内部声明函数,并加上inline,然后在类体外给出函数定义,这样也是内敛函数。
- 成员函数在类体外定义:类体内必须有函数原型,类体外函数定义前必须用"类名::"作用域运算符。
- 类名的定义遵循一般的标识符命名规则,即字母,数字和下划线的组合,大小写敏感,但不能以数字开头,也不能和系统中使用的关键字完全相同。
- 类定义以“:” 结束,大括号中部分的称为类体。
- “访问范围说明符”一共有三种,分别是public(公有),private(私有),和protected(保护)。在类定义中可以以任意的次序出现任意多次。
- 如果成员变量是私有的,那么在类外不可访问,所以通常在类内会为每个成员变量定义一对访问函数,一个用来设置这个成员变量的值,常称为设置函数:另一个用来获取这个成员变量的值,常称为 获取函数。
自定义日期类myDate:
#include <iostream>
#include <string>
#include <windows.h>
using namespace std;
class myDate
{
private:
int year, month, day;
public:
/*构造函数是类的一种特殊的成员函数,
它会在每次创建类的新对象时执行,类似python的__init__*/
myDate(); // 构造函数1
myDate(int,int,int); // 构造函数2
void setDate(myDate); // 设置日期
void setDate(int,int,int); // 设置日期
myDate getDate(); // 获取日期
void setYear(int); // 设置年份
int getMonth(); // 获取月份
void printDate() const; // 打印日期
};
myDate::myDate()
{
// 实例化后给类私有属性赋值
year = 1970, month = 1, day = 1;
cout<<"在声明类时执行-----> myDate myClass1; " << endl;
cout<<"这是构造函数1:" << year<<"-"<< month<<"-" << day<< endl;
Sleep(500);
}
myDate::myDate(int y,int m,int d)
{
year = y,month = m,day = d;
cout<<"在声明类时执行-----> myDate myClass2(2202,3,4); " << endl;
cout<<"这是构造函数2:" << year<<"-"<< month<<"-" << day<< endl;
Sleep(500);
}
void myDate::setDate(myDate oneD)
{
year = oneD.year,month = oneD.month,day = oneD.day;
cout << "这是设置时间函数:"<<endl;
cout << oneD.day<<"-->天数, "<< oneD.month << "-->月份, "<< oneD.year << "-->年份. "<<endl;
Sleep(500);
}
void myDate::setDate(int y,int m,int d)
{
year = y,month = m,day = d;
cout << "这是设置时间函数:"<<endl;
cout << day<<"-->天数, "<< month << "-->月份, "<< year << "-->年份. "<<endl;
Sleep(500);
}
myDate myDate::getDate()
{
return *this;
}
void myDate::setYear(int y)
{
year = y;
return;
}
int myDate::getMonth()
{
cout << "月份为:"<< month <<endl;
return month;
}
void myDate::printDate() const
{
cout << year << "-"<< month << "-"<< day <<endl;
return;
}
int main()
{
myDate myClass1;
myDate myClass2(2202,3,4);
myClass1.setDate(myClass1);
myClass2.setDate(2022,3,3);
myClass1.getMonth();
myClass1.printDate();
std::cout<<"hello world";
Sleep(5);
return 0;
}
结果图:
类的成员变量不能在声明时赋初:
第四行改为:int Num,Score; 类的成员变量
不能在声明时赋初值。
四 、类的示例程序剖析
知识点1: 成员变量与成员函数的定义:
- 一个完整的c++程序包括: 主函数main、用户定义的任意多个的类以及全局函数、全局说明、注释、头文件
- 成员变量一般定义为私有访问权限,仅在本类中访问。
- 使用类类型定义的变量称为类对象,每个对象都有各自的储存空间。
- 在类体外定义成员函数时,要指明类的名称。因为函数体代码较长,在类体内仅给出成员函数的原型,在类体外给出对应的函数体。如果在函数体定义在类体内,系统将视为内敛函数。
- 在类中定义的成员函数允许重载。成员函数在内存中只有一份,每个对象共享。
知识点2: 创建类对象的基本形式
1. 定义对象的两种方法:
(1)方法一:
类名 对象名; // 多个对象可用逗号隔开一起定义
类名 对象名(参数);
类名 对象名 = 类名(参数);
(2)方法二 :
类名 *指针名 = new 类名; // 成员变量不能进行初始化
类名 *指针名 = new 类名(); // 编辑器提供的构造函数进行初始化
类名 *指针名 = new 类名(参数);
2、对象的引用、指针、数组
(1) 对象的引用
类名 &对象引用名 = 对象;
(2) 对象的指针
类名 *对象指针名 = 对象的地址;
(3) 对象数组
类名 对象数组名[数组大小]
五 、访问对象的成员
1、 使用对象访问成员,通过对象访问的一般格式:
对象名.成员变量名
对象名.成员函数名(参数)
要注意:成员的访问权限
私有成员在类的外部不可以直接调用
代码:
#include<iostream>
#include<string>
#include <windows.h>
using namespace std;
class myDate
{
private:
int year,month,day;
public:
myDate();
myDate(int,int,int);
void setDate(int,int,int);
void setDate(myDate);
void printDate() const;
};
void myDate::printDate() const
{
cout << "生日:"<< year << "年"<< month<<"月" <<day <<"日" <<endl;
}
myDate::myDate(){
}
myDate::myDate(int y,int m,int d){
year = y,month = m,day = d;
}
void myDate::setDate(int y,int m,int d)
{
year = y,month = m,day = d;
}
void myDate::setDate(myDate oneD)
{
year = oneD.year,month = oneD.month,day = oneD.day;
}
class Student
{
private:
string name;
myDate birthday; // 使用类方法来产生对象,对象名称是birthday
public:
Student();
void setStudent(string, myDate);
void PrintStudent();
};
Student::Student()
{
}
void Student::setStudent(string name_, myDate d)
{
name = name_;
birthday.setDate(d);
};
void Student::PrintStudent()
{
cout <<"姓名:"<< name<<endl;
birthday.printDate();
}
int main()
{
Student ss;
int y,m,d;
string name_;
cout << "请输入学生的姓名和生日,生日以\"年 月 日\"的次序输入:";
cin >> name_ >> y>> m>> d;
ss.setStudent(name_,myDate(y,m,d));
ss.PrintStudent();
return 0;
}
2、使用指针访问,格式为:
指针->成员名
main代码:
int main()
{
Student ss;
int y,m,d;
string name_;
Student *sp = &ss; // sp是对象的指针, 指向对象ss的地址
cout << "请输入学生的姓名和生日,生日以\"年 月 日\"的次序输入:";
cin >> name_ >> y>> m>> d;
sp->setStudent(name_,myDate(y,m,d));
sp->PrintStudent();
// ss.setStudent(name_,myDate(y,m,d));
// ss.PrintStudent();
return 0;
}
3、使用引用访问,格式为:
引用名.成员名
main代码:
int main()
{
Student ss;
int y,m,d;
string name_;
Student &sy = ss; // sy是ss的别名
cout << "请输入学生的姓名和生日,生日以\"年 月 日\"的次序输入:";
cin >> name_ >> y>> m>> d;
// sp->setStudent(name_,myDate(y,m,d));
// sp->PrintStudent();
sy.setStudent(name_,myDate(y,m,d));
sy.PrintStudent();
return 0;
}