目录
前言
一、C语言和C++的区别
二、输入输出
1.C标准库的移植
2.C++标准输入输出流
三、引用变量
四、函数的区别
五、用户定义类型
六、动态内存分配
七、学生成绩分析
插播一条消息 this 指针
八、class详解
九、默认构造函数
十、运算符重载
十一、string类型和析构函数
十二、派生、继承、虚函数
十三、内联函数
总结
C语言想过渡C++,不想重新学习但又不想囫囵吞枣。这是本人的学习笔记
C++语言是C语言的扩展和增强,由原来的面向过程编程转变成面向对象、通用算法(泛型编程)
由于C++是C语言的扩展,所以C语言程序也是C++程序,原有的.c 程序可以在 .cpp的文件上编译运行。
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++中仍然可行。
头文件: 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; }
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 和 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; }
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++看似简单,但其实还是要熟悉从面向过程到面向对象编程的转变,这个作文本人的一个学习笔记,应该有很多不足、不完善的地方,努力学习ing。