本文最后更新于:2023年3月31日 晚上
C++ 基础复习笔记
1、Hello World
1 2 3 4 5 6 7
| #include <iostream> using namespace std;
int main(void){ cout<< "Hello world!"<<endl; return 0; }
|
2、 别名
1 2
| typedef double Area,Volume; using Area = double;
|
3、 auto与decltype
1 2
| auto i=0,j=1; autp i=0,pi=3.14;
|
4、函数
1 2 3 4 5 6 7 8 9 10
| double power(double x,int n){ double val = 1.0; while(n--) val*=x; return val; }
int power(int x,int y){ //函数重载 }
|
5、类与对象
类的定义
1 2 3 4 5 6 7 8 9
| class Clock { public: void setTime(int newH, int newM, int newS); void showTime(); private: int hour, minute, second; };
|
函数成员
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21
| class Clock { public: void setTime(int newH, int newM, int newS); void showTime(); } private: int hour, minute, second; };
void Clock::setTime(int newH,int newM,int newS){ hour = newH; minute = newM; secodne = newS; }
void Clock::showTime(){ cout<<"Hour:"<<hour<<"Minutes:"<<minute<<"Seconds"<<second<<endl; }
|
内联函数的两种写法
1 2 3 4 5 6 7 8 9 10 11 12 13 14
| class Clock{ public: void setTime(int newH,int newM,int newS); void showTime(); void func(){ cout<<"这是内联函数的隐式写法"<<"当代码简单,用的次数比较多的时候可以用内联函数" } private: int hour,minute,second; }
inline void Clock::func(){ cout<<"这是内联函数的显式写法" }
|
构造函数与析构函数
作用:在对象被创建时利用特定的值构造对象,将对象初始化为一个特定的状态。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18
| class Clock { public: Clock(); Clock(int newH,int newM,int newS); void setTime(int newH, int newM, int newS); void showTime(); private: int hour, minute, second; };
Clock::Clock(int newH,int newM,int newS):hour(new) int mian(void){ Clock(); Clock(0,0,0); }
|
委托构造函数
构造函数 class_c(int, int, int) 首先调用构造函数
class_c(int, int),该构造函数反过来调用
class_c(int)。
每个构造函数将仅执行其他构造函数不会执行的工作。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43
| class class_c { public: int max; int min; int middle;
class_c() {} class_c(int my_max) { max = my_max > 0 ? my_max : 10; } class_c(int my_max, int my_min) { max = my_max > 0 ? my_max : 10; min = my_min > 0 && my_min < max ? my_min : 1; } class_c(int my_max, int my_min, int my_middle) { max = my_max > 0 ? my_max : 10; min = my_min > 0 && my_min < max ? my_min : 1; middle = my_middle < max && my_middle > min ? my_middle : 5; } };
class class_c { public: int max; int min; int middle;
class_c(int my_max) { max = my_max > 0 ? my_max : 10; } class_c(int my_max, int my_min) : class_c(my_max) { min = my_min > 0 && my_min < max ? my_min : 1; } class_c(int my_max, int my_min, int my_middle) : class_c (my_max, my_min){ middle = my_middle < max && my_middle > min ? my_middle : 5; } }; int main() {
class_c c1{ 1, 3, 2 }; }
|
复制构造函数
作用:使用一个已经存在的对象,去初始化同类的一个新对象。把初始对象的每个数据成员的值都复制到新建立的对象中。在用户没有指定复制构造函数时,系统会自动生成复制构造函数。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19
| class Point{ public: Point(int xx=0,int yy=0){ x=xx; y=yy; } Point (Point &p); int getX(){return x;} int getY(){return y;} private: int x,y; } Point::Point(Point &p){ x = p.x; y = p.y; cout<<"Calling the copy constructor"<<endl; }
|
析构函数
作用:用来完成对象被删除前的一些清理工作。在对象生命周期即将结束的时候被自动调用,不接受任何参数。
1 2 3 4 5 6 7 8 9
| class Clock{ public: Clock(); void setTime(int newH,int newM,int newS); void showTime(); ~Clock(){} private: int hour,minute,second; }
|
枚举类型与Union类型
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35
|
#include <iostream>
using namespace std;
enum GameResult {WIN,LOSE,TIE,CANCEL};
int main(void) { GameResult result; enum GameResult omit = CANCEL; for (int count = WIN; count <= CANCEL; count++) { result = GameResult(count); if (result == omit) { cout << "The Game was cancelled" << endl; } else { cout << "The game was played"<<endl; if (result == WIN) { cout << "Won" << endl; } else { cout << "Lose" << endl; } } }
return 0; }
|
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58
| #include <iostream> #include <string>
using namespace std;
class ExamInfo { public: ExamInfo(string name,char grade); ExamInfo(string name, bool pass); ExamInfo(string name, int percent); void show();
private: string name; enum { GRADE, PASS, PERCENTAGE }mode; union { char grade; bool pass; int percent; }; };
ExamInfo::ExamInfo(string name, char grade) :name(name), mode(GRADE), grade(grade) {}; ExamInfo::ExamInfo(string name, bool pass) :name(name), mode(PASS), pass(pass) {}; ExamInfo::ExamInfo(string name, int percent) :name(name), mode(PERCENTAGE), percent(percent) {}; void ExamInfo::show() { switch (mode) { case ExamInfo::GRADE: cout<<grade; break; case ExamInfo::PASS: cout << pass ? 0 : 1; break; case ExamInfo::PERCENTAGE: cout << percent; break; default: break; } cout << endl; }
int main(void) { ExamInfo course1("CPU", 'N'); ExamInfo course2("GPU", 0); ExamInfo course3("Tem", 80); course1.show(); course2.show(); course3.show(); return 0; }
|
综合案例
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77
| #include <iostream> #include <cmath>
using namespace std; class SavingAccount { private: int id; double balance; double rate; int lastDate; double accummulation; void record(int date,double amount); double accumulate(int date) const { return accummulation + balance * (date - lastDate); } public: SavingAccount(int date, int id, double rate); int getID() { return id; } double getBalance() { return balance; } double getRate() { return rate; } void deposit(int date, double amount); void withdraw(int date, double amount); void settle(int date); void show(); };
SavingAccount::SavingAccount(int date, int id, double rate) :id(id), balance(0), rate(rate), lastDate(date), accummulation(0) { cout << date << "\t#" << id << "is created" << endl; }
void SavingAccount::record(int date, double amount) { accummulation = accumulate(date); lastDate = date; amount = floor(amount * 100 + 0.5) / 100; balance += amount; cout << date << "\t#" << id << "\t" << amount << "\t" << balance << endl; }
void SavingAccount::deposit(int date, double amount) { record(date, amount); }
void SavingAccount::withdraw(int date, double amount) { if (amount > getBalance()) { cout << "Error : not enough money" << endl; } else { record(date, -amount); } }
void SavingAccount::settle(int date) { double interest = accumulate(date) * rate / 365; if (interest != 0) { record(date, interest); } accummulation = 0; }
void SavingAccount::show() { cout << "#" << id << "\tBalance:" << balance<<endl; }
int main(void) { SavingAccount sa0(1, 21325302, 0.015); SavingAccount sa1(1, 58320212, 0.015); sa0.deposit(5, 5000); sa1.deposit(25, 10000); sa0.deposit(45, 5500); sa1.withdraw(60, 4000); sa0.settle(90); sa1.settle(90); sa0.show(); sa1.show();
return 0; }
|
深度搜索
位域
将类中的多个数据成员打包,从而使不同成员可以共享相同的字节的机制。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15
|
class student { public: student(unsigned number, Level level, Grade grade) :number(number), level(level), grade(grade) {}; void show(); private: unsigned number : 27; Level level : 2; Grade grade : 2; };
|
6、数据的共享与保护
作用域
类作用域
enum作用域
1 2 3 4 5 6
| enum color {red,yellow,green}; enum class color2 {red,yellow,green};
color c =red; color c2 = color::red; color2 c3 = color2::red;
|
生存周期
静态生存周期
1 2 3 4 5
|
static int i = 5; static int j;
|
类的静态成员
类属性:某个属性为整个类所共有,不属于某个具体对象,采用static声明
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57
| #include <iostream>
using namespace std;
class Point { public: Point(int x = 0, int y = 0); Point(Point& p); ~Point(); int getX(); int getY(); static void showCount(); private: int x, y; static int count; };
Point::Point(int x , int y ) :x(x), y(y) { count++; }; Point::Point(Point& p) :x(p.x), y(p.y) { count++; }; Point::~Point() { count--; }
int Point::getX() { return x; }
int Point::getY() { return y; }
void Point::showCount() { cout << "Object count=" << count << endl; }
int Point::count = 0;
int main() { Point::showCount(); Point a(4, 5); cout << "Point A " << a.getX() << "," << a.getY() << endl; a.showCount();
Point b(a); cout << "Point B " << b.getX() << "," << b.getY() << endl; Point::showCount(); return 0; }
|
静态成员函数中访问类的非静态成员必须指明对象。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30
| #include<iostream> using namespace std;
class A { public : A(); static void f(); static void g(A a); private: int x; static int y; };
A::A() { cout << x; };
void A::f() { cout << x; cout << y; };
void A::g(A a) { cout << a.x; } int main() { return 0; }
|
友元
友元关系提供了不同类或对象的成员函数之间,类的成员函数与一般函数之间进行数据共享的机制。通过友元关系,一个普通函数或者类的成员函数可以访问封装于另一个类中的函数。
友元关系单向、不能传递、不能继承。
友元函数
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17
| class Point{ public: Point(int x=0,int y=0); int getX(); int getY(); friend float dist(Point &p1,Point &p2); private: int x,y; };
float dist(Point &p1,Point &p2){ double x = p1.x-p2.x; double y = p1.y-p2.y; return static_cast<float>(sqrt(x*x+y*y)); }
|
友元类
A为B的友元类,A类中所有成员都是B的友元函数,都可以访问B类的私有和保护成员
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20
| class A{ public: void display(); friend class B; private: int x; };
class B{ public: void set(int i); void display(); private: A a; };
void B::set(int i){ a.x = i; }
|
new和delete
先分配memory,再调用ctor构造函数
1 2 3 4 5 6 7
| Complex* pc = new Complex(1,)2;
Complex* pc;
void* men = operate new (sizeof(Complex)); pc = static_cast<Complex*>(mem); pc->Complex::Complex(1,2);
|
先调用dtor析构函数,再释放Memory
1 2 3 4 5 6
| String* ps = new String("Hello"); ... delete ps;
String::~String(ps); operator delete (ps);
|
const
修饰常量、常对象。常对象不能被更新。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40
|
类型说明符 函数名(参数表) const;
#include<iostream> using namespace std;
class R { public: R(int r1, int r2); void print(); void print2() const; private: int r1, r2; };
R::R(int r1, int r2) :r1(r1), r2(r2) {}; void R::print() { cout << r1 << ":" << r2 << endl; }
void R::print2() const { cout << r1 << ";;" << r2 << endl; }
int main() { R a(5, 4); a.print(); a.print2(); const R b(20, 52); b.print2(); return 0; }
|
常数据成员与静态常数据成员
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31
| #include<iostream> using namespace std;
class A { public: A(int i); void print(); private: const int a; static const int b; static const int b = 10; };
const int A::b = 10;
A::A(int i) :a(i) {};
void A::print() { cout << a << ":" << b << endl; }
int main() { A a1(100), a2(20); a1.print(); a2.print(); return 0; }
|
常引用
常引用的对象不能被更新。函数中无需修改两个传入对象的值,因此将传参方式改为传递常引用更合适。
无需改变其值的参数,不宜使用普通引用方式加以传递。可以采用传值方式或者传递常引用方式。
对于大对象来说,传值耗时较多,因此传递常引用为宜。
复制构造函数的参数也宜采用常引用的方式。
1 2 3 4 5 6 7
| class Point{ public: ... friend float dist(const Point &p1,const Point &p2); }
float dist(cosnt Point &p1,const Point &p2){};
|
总结
const 数据成员
只在某个对象生存期内是常量,而对于整个类而言却是可变的。因为类可以创建多个对象,不同的对象其
const 数据成员的值可以不同。所以不能在类的声明中初始化 const
数据成员,因为类的对象没被创建时,编译器不知道 const
数据成员的值是什么。
const
数据成员的初始化只能在类的构造函数的初始化列表中进行。要想建立在整个类中都恒定的常量,应该用类中的枚举常量来实现,或者static
cosnt。
cosnt 成员函数主要目的是防止成员函数修改对象的内容。即 const
成员函数不能修改成员变量的值,但可以访问成员变量。当方法成员函数时,该函数只能是
const 成员函数。
1 2 3 4 5 6 7 8 9 10 11 12 13
| class Test{ public: Test(); enum {size1=100,size2=200}; private: const int a; static int b; conststatic int c; }; Test::Test():a(0); int Test::b=0; const intTest::c=0;
|
const 与 static
变量定义很重要
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33
| #pragma once class Test { private : int var1; const int var2 ; static int var3; static const int var4=4444; static const int var44; public: Test(void); ~Test(void); };
#include ".\test.h" int Test::var3 = 3333333;
Test::Test(void):var1(11111),var2(22222)正确的初始化方法 { var1 =11111; var3 =44444; } Test::~Test(void){}
|
mutable
mutalble使得常成员函数可以修改他们的值。被mutable修饰的成员对象任何时候都不会被视为常对象。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16
| class Line{ public: Line(const Point &p1,const Point &p2):p1(p1),p2(p2),len(-1){}; double getLen() const; private: Point p1,p2; mutable double len; }; double Line::getLen() const{ if(len<0){ double x = p1.getX()-p2.getX(); double y = p1.getY()-p2.getY(); len = sqrt(x*x+y*y); } return len; }
|
文件结构与外部引用
C++文件结构
1 2 3
| .h 头文件 类定义文件 .cpp 类实现文件 .cpp 类使用文件
|
外部引用
一个变量除了在定义他的源文件中引用,还被其他文件引用。需要加extern文件关键字。
extern关键字声明的变量,如果同时指定类初值,则是定义性声明(声明的同时定义,分配内存初始化),否则是引用性声明。
通常情况下,变量和函数的定义都放在源文件中,而对外部变量和外部函数的引用性声明则放在头文件中。
1 2 3 4 5
| int i = 3;
extern int i ;
|
将变量和函数限制在编译单元内
1 2 3 4 5 6 7 8
|
namespace{ int n; void f(){ n++; } }
|
编译
预定义
条件编译
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35
| #if ... ... #endif
#if ... ... #else ... #endif
#if ... ... #elif ... ... #elif ... ... #else ... ... #endif
#ifdef ... ... #else ... #endif
#ifndef ... ... #endif
|
defined操作符
defined是一个预处理操作符,而不是指令,因此不用#开头。
1 2 3 4 5 6 7 8 9 10
| #ifndef MYHEAD_H #define MYHEAD_H ... #endif
#if !defined(MYHEAD_H) #define MYHEAD_H ... #endif
|
堆栈内存管理
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16
| class Complex{...}; ... { Complex c1(1,2); Complex* p = new Complex(3); ... delete p; static Complex c2(1,2); }
|