目录
前言
熟能生巧
一、C语言和C++的区别
C++语言是C语言的扩展和增强,由原来的面向过程编程转变成面向对象、通用算法(泛型编程)
由于C++是C语言的扩展,所以C语言程序也是C++程序,原有的.c 程序可以在 .cpp的文件上编译运行。
二、输入输出
1.C标准库的移植
C++标准库中存在着很多C标准库的移植版本:
头文件:
C标准库的头文件xxx.h 基本上变为 cxxx 如下图:
//C语言头文件
#include<stdio.h> /*标准输入输出流函数*/
#include<string.h>
#include<math.h>
//C++头文件
#include<cstdio>
#include<cstring>
#include<cmath>
//例外 malloc 没有变化
#include<malloc.h>
看一些简单的例子
由此可以看出,适用于C语言的一些函数和操作,在C++中仍然可行。
2.C++标准输入输出流
头文件: iostream 包含C++标准额输入输出流函数
#include<iostream>
输出流函数:cout
输入流函数:cin
输入输出运算符: << 或 >>
o<<x,加入o是个对象,x是数据,o<<x的意思是把x的数据输入到对象o中,然后返回的是对象o
看第一个例子:
为了防止名字出现冲突,C++语言中设有名字空间,使用某些名字的时候需要标注名字空间,而cout 和 cin 都是在名字空间 std 中,因此,使用的时候必须声明此名字空间,一般来说有三种标注方法。方法如下:
第一种方法:
#include<iostream>
using namespace std;//第一种方法,在使用之前引用此名字空间中的所有
int main()
{
cout << "hallo world\n";
cout << 2 + 3 << endl;//endl是换行的意思,作用相当\n
return 0;
}
第二种方法:
#include<iostream>
using std::cout; //第二种方法,在使用之前标注:使用std名字空间内的cout
using std::endl: //第二种方法,使用std名字空间内的endl
int main()
{
cout << "hallo world\n";
cout << 2 + 3 << endl;//endl是换行的意思,作用相当\n
return 0;
}
第三种方法:
#include<iostream>
int main()
{
std::cout << "hallo world\n";//第三种方法:在使用之前标明出处 格式为std::
std::cout << 2 + 3 << std::endl;//每次使用都要标注
return 0;
}
输入输出的实例:
三、引用变量
实际上引用变量就是原来变量的别名,
地址和原变量的地址相同
void SWAP(int a, int b) {
int c = a;
a = b;
b = c;
cout << &a << endl;
}
void SWAP2(int& x, int& y) {
int c = x;
x = y;
y = c;
cout<< &x << endl;
}
int main()
{
int a = 1, b = 5;
cout << a << '\t' << b << endl;
cout << &a << endl;
SWAP(a, b);
cout << a << '\t' << b << endl;
SWAP2(a, b);
cout << a << '\t' << b << '\n';
return 0;
四、函数的区别
默认形参
函数重载
而下面这种调用方法是错的
函数模板
五、用户定义类型
string类型
vector 类模板:
#include<iostream>
#include<vector>
using namespace std;
int main()
{
//vector
// vector是向量,类似于数组,但可以动态增长
// vector是类模板,实例化产生一个类
// 如 vector<int> 产生一个数据类型是 int 的 vector<int> 类(向量)
// 同样,可以根据 vector<int> 类对象去访问其成员,如成员函数
// 也可以使用运算符进行运算
//
vector<int> k;
k = { 1,2,3,4,5 };
k.pop_back();//pop_back() 在结尾删除一个元素
k.push_back(6);//push_back() 在最后添加一个元素
for (size_t i = 0; i < k.size(); i++)
{
cout << k[i] << '-';
}
cout << endl;
// 类似的,还有如下函数
// clear() //清空所有元素
// empty() //判断vector是否为空,如果返回true为空
// erase() // 删除指定元素
k.erase(k.begin() + 1);
for (size_t i = 0; i < k.size(); i++)
{
cout << k[i] << '-';
}
cout << endl;
k.resize(3);//resize 重新定义k的大小
for (size_t i = 0; i < k.size(); i++)
{
cout << k[i] << '-';
}
cout << endl;
k.clear();
if (k.empty())
return 0;
for (size_t i = 0; i < k.size(); i++)
{
cout << k[i] << '-';
}
return 0;
}
iterator 迭代器
int main()
{
//iterator 是 C++的 迭代器
vector<int> k = { 1,2,3,4,5, };
vector<int>::iterator it;//这里创建一个 变量 it 来迭代
for (it = k.begin(); it != k.end(); it++)
{
cout << *it << ' ';
}
cout << endl;
for (it = k.begin(); it != k.end(); )
{
if (*it % 2 == 0)
{
it = k.erase(it);//删除 2 之后 it 指向 3 了
//删除之后返回的是下一个元素的位置
}
else it++;
}
cout << endl;
k = { 0,1,2,3,4,5,6,7,8,9, };
it = k.begin() + 2;
vector<int>::iterator it2 = k.end();
k.erase(it, it2);
for (it = k.begin(); it != k.end(); it++)
{
cout << *it << ' ';
}
return 0;
}
六、动态内存分配
int main()
{
//动态内存分配
//new用来申请新的内存块,delete用来释放
//数组的话用delete[]
int* p = new int[4];
for (size_t i = 0; i < 4; i++)//初始化
p[i] = i;
for (size_t i = 0; i < 4; i++)//遍历输出
cout << p[i] << '\t';
cout << endl;
char* s = (char*)p;
char ch = 'A';
int n2 = 4 * (sizeof(int) / sizeof(char));
for (int i = 0; i < n2; i++)//初始化
s[i] = ch + i;
for(int i = 0; i < n2; i++)//遍历输出
cout << s[i] << ' ';
cout << endl;
delete[] s;
return 0;
}
七、学生成绩分析案例
struct student {
string name;
double score;
void print();//函数声明
};
void student::print() //注意,函数实现在结构体外面,应该标注名字空间
{
cout << name << ' ' << score << endl;
}
int main()
{
vector<student> st;
while (1) {
student stu;
cout << "请输入姓名 成绩" << endl;
cin >> stu.name >> stu.score;
if (stu.score < 0)
break;
st.push_back(stu);
}
for (size_t n = 0; n < st.size(); n++) {//遍历查看输入的数据
st[n].print();
}
//vector<student>::iterator it;
//it = st.begin();
//it->print();
//下面输出最大,最小,以及平均数
int max = 0;
int min = 0;
double average = 0;
for (size_t n = 0; n < st.size(); n++) {
average += st[n].score;
if (st[max].score < st[n].score)
max = n;
if (st[min].score > st[n].score)
min = n;
}
st[max].print();
st[min].print();
cout << average / st.size() << endl;
return 0;
}
7.1、this 指针
struct student {
string name;
double score;
void print() {
cout << name << '\t' << score << endl;
}
//this指针
//成员函数内部隐含一个this指针
//实际上是
void print() {
cout <<this->name << '\t' <<this->score << endl;
}
};
八、class详解
基本运用
//class 和 struct 的区别
//struct 内部的成员默认是公开的(public)
//class 内部的成员默认的是私有的 (private)
class student {
private:
string name;
double score;
public:
void print() { cout << name << '\t' << score << endl; }
//如何在外部访问?
string get_name() { return name; }
double get_score() { return score; }
//如何在外部修改?
void set_name(string s) { name = s; }
void set_score(double s) { score = s; }
};
int main()
{
student std;
std.set_name("Li Hua");
std.set_score(98.7);
cout << std.get_name() << '\t' << std.get_score() << endl;
std.print();
return 0;
}
九、默认构造函数
在class结构类型内部存在一个默认构造函数
class student
{
string name;
double score;
public:
student(){};//默认构造函数是不带任何形参的
student(string n, double s)//这个就不是默认构造函数
{
name = n;
score = s;
}
}
int main()
{
student stu;//在定义变量的时候,调用默认构造函数。
student stus[4];//定义数组的时候 如果没有默认构造函数会出错
return 0;
}
十、运算符重载
运算符重载
输入输出 << >> 运算符只能在class外部重载
下标运算符 [] 只能内部实现
加减乘除 外部内部都可 只是实现方式不同
// 运算符重载
// 输入输出 << >> 运算符只能在class外部重载
// 下标运算符 [] 只能内部实现
// 加减乘除 外部内部都可 只是实现方式不同
class point {
double x, y;
public:
point() {};//这个是默认构造函数
//加法运算符的内部实现
point operator+(const point q) {
return point(this->x + q[0], this->y + q[1]);
}
//下标运算符重载(只可输出)
double operator[](int i) const{
if (i == 1) return y;
else if (i == 0) return x;
else throw "下标非法\n";
}
//下标运算符重载(可以输出,也可以修改)
double& operator[](int i) {
if (i == 1) return y;
else if (i == 0) return x;
else throw "下标非法\n";
}
//自己的构造函数,用来初始化
point(double x1, double y1)//这个不是默认构造函数
{
x = x1;
y = y1;
}
//友元函数
friend ostream& operator<<(ostream& o, point s);
friend istream& operator>>(istream& in, point& s);
};
//运算符 << 重载
ostream& operator<<(ostream& o, point s) {
cout << s.x << '-' << s.y << endl;
return o;
}
//运算符 >> 重载
istream& operator>>(istream& in, point& s) {
cin >> s.x >> s.y;
return in;
}
#if 0
//加法运算符的外部定义
point operator+(const point p, const point q) {
return point((p[0] + q[0]), (q[1] + p[1]));
}
#endif
int main()
{
//普通下标运算符的使用
point p(2, 3);
point pp[3] = { {1,1},{2,2,},{3,3,} };
cin >> p;
cout << p << endl;
cout << pp[0] << endl;
//下标运算符重载
point p(2, 10);
cout << p;
cout << p[0] << ',' << p[1] << endl;//实际上是p.operator[](0); p.operator[](1);
p[0] = 0;
p[1] = 1;
cout << p;
//加法 + 运算符重载
point p(1, 2), q(5, 6);
cout << p << q;
cout << p + q; // 内部 p.operator+(q); 外部 p.operator+(p, q)
return 0;
}
十一、string类型和析构函数
class String {
char* date;//C风格的字符串
int n;//字符的个数
public:
~String() {//析构函数
if (date)
delete[] date;
cout << n << "析构函数\n";
}
#if 1
String(String& s) {//默认拷贝构造函数 硬拷贝
cout << "拷贝构造函数\n";
date = new char[s.n + 1];
n = s.n;
for (int i = 0; i < n; i++)
date[i] = s[i];
date[n] = '\0';
}
#endif
String(const char* s=0) {//构造函数
cout << "构造函数\n";
if (s == 0) {
cout << "s==0\n";
date = 0;
n = 0;
return;
}
else {
const char* p = s;
while (*p != '\0') p++;
n = p - s;
date = new char[n+1];
for (int i = 0; i < n; i++)//初始化 赋值
date[i] = s[i];
date[n] = '\0';
}
}
char operator[](int i)const {//用来访问
if (i < n && i >= 0)
return date[i];
else throw"下标非法!\n";
}
char& operator[](int i) {//用来修改
if (i < n && i >= 0)
return date[i];
else throw"下标非法!\n";
}
int size() { return n; }//返回字符个数
friend ostream& operator<<(ostream& o, String s);
};
ostream& operator<<(ostream& o, String s) {
for (int i = 0; i < s.size(); i++) {
cout << s[i];
}
return o;
}
void f()
{
String str1, str2("hallo world");
cout << "在拷贝之前\n";
str2[1] = 'E';
cout << "在拷贝之后\n";
#if 1
str2[6] = 'W';
cout << str2 << endl;//拷贝构造函数
String s3 = str2;//拷贝构造函数
s3[0] = 'o';
cout << str2 << endl;//拷贝构造函数
cout << s3 << endl;//拷贝构造函数
#endif
}
int main() {
f();
}
十二、派生、继承、虚函数
//继承 Inheritance 和 派生 derivation :一个派生类(derived class)
//从一个或多个父类(parent class)/ 基类(base class)继承,
//即继承父类的属性和行为,但也有自己的专属属性
class Employee {
string name;
public:
virtual void print() {//virtual是虚函数的关键字
cout << name << endl;
}
Employee(string s = "no_Name") {
name = s;
}
string get_name() {
return name;
}
};
//注意派生的格式 在后面加上:基类
class Manager :public Employee{//manager 是 employee的派生
//此处继承employee的name
int level;
public:
Manager(string n, int l) :Employee(n), level(l) {}
void print();
};
//外部实现类对象 注意格式
void Manager::print() {
cout << get_name() << '\t' << level << endl;
}
//也可以从多个类派生出一个类
class One {
};
class Two {
};
//此处注意格式,继承类的后边要加上:public基类 如果继承多个基类 则中间用 ,隔开
class Multiple :public One, public Two {
};
int main()
{
string name;
int lev;
char sss;
Employee* arr[10];
int num = 0;
cout << "请输入命令,m表示经理,e表示雇员\n";
while (cin >> sss) {
if (sss == 'm' || sss == 'M') {
cout << "请输入姓名和级别\n";
cin >> name >> lev;
Manager* p = new Manager(name, lev);
arr[num] = p;
num++;
}
else if (sss == 'e' || sss == 'E') {
cout << "请输入姓名\n";
cin >> name;
Employee* p = new Employee(name);
arr[num] = p;
num++;
}
else break;
cout << "请输入命令\n";
}
for (int i = 0; i < num; i++) {
arr[i]->print();
}
return 0;
}
十三、内联函数
//内联函数 关键字:inline
// 对于不包含循环的函数,可以使用内联函数,
// 编译时 编译器直接用代码替换 不创建函数展开 可以减少调用开销
inline double distance(double a, double b)
{
return sqrt(a * a + b * b);
}
int main() {
cout<<distance(1, 2);
//实际上是cout<<sqrt(a * a + b * b);
return 0;
}
总结
C过渡C++看似简单,但其实还是要熟悉从面向过程到面向对象编程的转变。多多上手,在实操中深入了解。Practice makes perfect .