c++面向对象程序设计课程笔记(简单易于理解) 您所在的位置:网站首页 ufc课程笔记 c++面向对象程序设计课程笔记(简单易于理解)

c++面向对象程序设计课程笔记(简单易于理解)

2024-06-11 10:24| 来源: 网络整理| 查看: 265

目录 第一章1. 概念性的名词:第二章2.1 命名空间2.2 define 和 const的差异2.3 函数原型c与c++的区别2.4 基本数据类型c++中的bool类型运算优先级、类型转换 2.5 引用2.6 内联函数2.7 带默认参数值的函数默认参数值设定默认参数值的说明次序默认参数值与函数的调用位置 2.8 函数重载函数重载的概念 2.9 new 和 delete 动态分配内存空间分配和释放动态数组new ,delete 和 malloc free 的异同 第三章3.1类与对象的定义类的语法定义类内初始值成员函数的定义类成员的访问控制 3.2 对象的语法定义3.3 构造函数基本概念构造函数的作用构造函数的形式构造函数的调用方式默认构造函数隐含生成的构造函数 3.4 拷贝构造函数拷贝构造函数的定义 3.5 析构函数3.6 类与结构体结构体的基本概念两者相同点两者差别点 3.7 对象数组和对象指针对象数组对象指针this 指针 3.8类的静态数据成员静态数据成员类的静态函数成员 3.9 类的友元友元函数友元类类的友元关系是单向的 3.10常类型常对象常成员 3.11 string 类 第四章4.1 继承与派生概述目的 4.2单继承时派生类的定义4.3 多继承时派生类的定义4.4 继承方式4.5 派生类的构造函数4.6 同名成员4.7 虚基类虚基类构造函数的调用顺序 第五章5.1 多态性运算符重载双目运算符重载规则前置单目运算符重载规则后置单目运算符 ++和--重载规则 第八章8. 容器8.1 vector (向量/动态数组)`vector 定义`:` vector 遍历`:`:vector中常用函数 8.2 map(映射)8.2.1如何理解map中的映射:8.2.2如何定义map:8.2.3map的访问:8.2.4map常用函数:8.2.5常见用途: 8.3set(集合)8.3.1set的定义8.3.2set内元素的访问8.3.3set常用函数: 8.4 stack8.4.1 stack 的定义8.4.2 stack 容器内元素的访问8.4.3stack常用函数: 8.5 queue队列8.5.1 queue 的定义8.5.2 queue 容器内元素的访问8.5.3queue常用函数:

第一章 1. 概念性的名词:

对象:

一般意义上的对象:现实世界中实际存在的事物。面向对象方法中的对象:程序中用来描述客观事物的实体。

抽象与分类

将有关事物共性归纳、集中的过程,即分类依据的原则——抽象;抽象出同一类对象的共同属性和行为形成类(“类”是一组具有相同属性和行为的对象的抽象);类与对象是类型与实例的关系,抽象和具体的关系。 例如:抽象实例——钟表 // 数据抽象: int hour,int minute,int second //代码抽象: setTime(),showTime() class Clock { public: void setTime(int newH, int newM, int newS); void showTime(); private: int hour, minute, second;};

封装

把数据和实现操作的代码集中起来放在对象内部,隐蔽对象的内部细节;对外形成一个边界;只保留有限的对外接口;使用方便、安全性好。实现封装:类声明中的 {} 例: class Clock { public: void setTime(int newH, int newM, int newS); void showTime(); private: int hour, minute, second; };

继承

意义在于软件复用;改造、扩展已有类形成新的类。若类之间有继承关系,则它们之间具有下列几个特性 类间具有共享性(包括数据和操作代码的共享)类间具有差别或者新增部分(可以加入自己所特有的新特性)类间有层次结构(直接基类,间接基类,a->b->c) 多继承和单继承 单继承:每个派生类只直接继承了一个基类的特征多继承:多个基类派生出一个派生类(基类-父类,派生类-子类)

多态

同样的消息作用在不同对象上,可以引起不同的行为。同一名称,不同的功能实现方式。目的:达到行为标识统一,减少程序中标识符的个数。实现:重载函数和虚函数 第二章 2.1 命名空间

避免命名冲突 std 是 C++标准库的命名空间( namespace)名 using namespace std 表示打开 std 命名空间

2.2 define 和 const的差异 常量定义,const 与define const 可以定义常量的类型 例如:const int a = 100; define 可以定义语句或片段 例如:#define ADD(a, b) ((a)+(b)) 必须要加括号,防止宏定义中部分替换而导致的运行错误。const 与指针的使用 指向常量的指针: 不能改变常量的值,但是可以改变指针的地址 const char * name = "change" ; // 可以理解为,const *name ,其中*name 是一个普通常量,因此常量的值是不能改变的 因此:name[3] = 'a' 是不可法的 name = "zhang" 是合法的,相当于 string t = "zhang" , name = &t;//这个时候仅仅只是改变了name指针变量所指向的地址。

常指针:不能改变指针的地址,但是可以改变指针所指向常量的值

char * const name = "chen"; name[3] = 'a'; //合法 name = "zhang" //不合法

指向常量的长指针:不能改变指针的地址,也不能改变指针所指向常量的值

tip: name 指针变量,表示地址。不好理解的话,可以想到数组,数组就是一个特殊的指针,int a[10] ,其中a,就是表示数组a[0]的地址。 如果还是不能理解的话可以看看c语言中指针的知识点: 这是本人写的相关博客连接:c语言重难点笔记

2.3 函数原型c与c++的区别

函数原型格式:返回类型名 函数名 (参数表); //注意这个分号 c 与 c++ 的区别在于:

在c中,可以对函数原型进行简化: 可以省略参数表,返回类型名。c++中,则不能省略 其主要目的:让c++编译程序进行检查,已确定调用函数的参数以及返回值类型与事先定义的是否相同。 如果没有注明参数表,则说明其为void c++中,main函数一定要为int 类型 2.4 基本数据类型 c++中的bool类型 只有两个值:true(真) 、false(假)常用来表示关系比较、相等比较或逻辑运算的结果所有⾮零值解释为 true ,零值解释为 false直接赋值⼀个数字给 bool 变量它会⾃动根据 int 值是不是零来决定 给 bool 变量赋值 true 还是 false

在这里插入图片描述

运算优先级、类型转换

在这里插入图片描述

2.5 引用

引用(&)是标识符的别名;

定义一个引用时,必须同时对它进行初始化,使它指向一个已存在的对象。 int i, j; int &ri = i; //定义 int 引用 ri,并初始化为变量 i 的引用 j = 10; ri = j; //相当于 i = j; 一旦一个引用被初始化后,就不能改为指向其它对象。变量 i 和引用 j 占用内存的同一位置,i 和 j 同时跟新。 指针与引用的差别: 指针不同在于其仅仅只是指向了 i 的地址,只要 i 的地址不改变,i的值发生改变,那么*j的值也会跟着发生改变。引用可以作为形参 #include using namespace std; void swap1(int& a, int& b) { int t = a; a = b; b = t; } void swap2(int a, int b) { int t = a; a = b; b = t; } int swap3(int a, int b) { int t = a; a = b; b = t; return a,b; } int main() { int x = 5, y = 10; cout double r = 3.0; double area = calArea(r); cout add(10,20); //10+20 add(10); //10+6 add(); //5+6 } 默认参数值的说明次序 有默认参数的形参必须列在形参列表的最右,即默认参数值的右面不能有无默认值的参数;调用时实参与形参的结合次序是从左向右。 int add(int x, int y = 5, int z = 6);//正确 int add(int x = 1, int y = 5, int z);//错误 int add(int x = 1, int y, int z = 6);//错误 默认参数值与函数的调用位置 如果一个函数有原型声明,且原型声明在定义之前,则默认参数值应在函数原型声明中给出;如果只有函数的定义,或函数定义在前,则默认参数值可以函数定义中给出。 //原型声明在前 int add(int x = 5,int y = 6); int main() { add(); } int add(int x,int y) { //此处不能再指定默认值 return x + y; } //只有定义,没有原型声明 int add(int x = 5,int y = 6) { return x + y; } int main() { add(); } 2.8 函数重载 函数重载的概念

motivation: 解决c语言中,函数名必须唯一的不便之处。 C++允许功能相近的函数在相同的作用域内以相同函数名声明,从而形成重载。方便使用,便于记忆。

重载的条件 可以是形参类型不同 int add (int x ,int y); float add(float x , float y); 形参个数不同 int add (int x , int y) ; int add(int x , int y, int z); 1和2都满足 注意: int add (int x, int y); int add (int a , int b) ; / /错误!编译器不以形参名来区分函数 int add (int x ,inty); void add(int x , int y); //错误!编译器不以返回值来区分函数

例题:

编写两个名为 sumOfSquare 的重载函数,分别求两整数的平方和及两实数的平方和。 #include using namespace std; int sumOfSquare(int a, int b) { return a * a + b * b; } double sumOfSquare(double a, double b) { return a * a + b * b; } int main() { int m, n;cout m >> n; cout cout cout return y; } void move(int newX, int newY) { x = newX; y = newY; } private: int x, y; }; int main() { cout cout cout return y; } void move(int newX, int newY) { x = newX; y = newY; } private: int x, y; }; int main() { Point *ptr = new Point[2]; //创建对象数组 ptr[0].move(5, 10); //通过指针访问数组元素的成员 ptr[1].move(15, 20); //通过指针访问数组元素的成员 cout public: void setTime(int newH, int newM, int newS); void showTime(); private: int hour = 0, minute = 0, second = 0; } 成员函数的定义 方式一: 在类声明中只给出成员函数的原型,而将成员函数的定义放在类的外部。 成员函数在类外的定义: 返回值类型 类名::成员函数名(参数表){ 函数体 }

“::” 作用域运算符,在类名和函数名之间加上作用域运算符“::” ,用于声明这个成员函数时属于哪几类的;在局部变量的作用域内使用使用同名的全局变量,可以使用 “::",来区分局部变量和全局变量,::变量名 表示全局变量。

这种方式有利于减少类体的长度,增加类的可读性,将类的接口与类的实现细节相分离,隐藏执行细节。

类成员的访问控制

数据成员和成员函数一般统称为类的成员。

公有类型成员 在关键字public后面声明,它们是类与外部的接口,任何外部函数都可以访问公有类型数据和函数。 私有类型成员 在关键字private后面声明,只允许本类中的函数访问,而类外部的任何函数都不能访问。如果紧跟在类名称的后面声明私有成员,则关键字private可以省略。 保护类型成员 与private类似,其差别表现在继承与派生时对派生类的影响不同

注意:在默认情况下(即没有指定属于私有或共有时),类中的成员是私有的。因此一个类中没有申明成员类型,则成员都为私有类型成员,则类外对象不能访问类内成员

3.2 对象的语法定义 类名 对象名; 例:Clock myClock;类成员的访问权限 类中成员互相访问 直接使用成员名访问类外访问 使用“对象名.成员名”方式访问 public 属性的成员。 例 钟表类 类的定义 #include using namespace std; class Clock{ public: void setTime(int newH = 0, int newM = 0, int newS = 0); void showTime();private: int hour, minute, second; } 成员函数的实现 void Clock::setTime(int newH, int newM, int newS) { hour = newH; minute = newM; second = newS; } void Clock::showTime() { cout public: 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(newH),minute(newM), second(newS) { } int main() { Clock c(0,0,0); //自动调用构造函数 c.showTime(); return 0; } //构造函数例题二 class Clock { public: Clock(int newH, int newM, int newS); //构造函数 Clock(); //默认构造函数void setTime(int newH, int newM, int newS); void showTime(); private: int hour, minute, second; }; Clock::Clock(): hour(0),minute(0),second(0){ }//默认构造函数 //其它函数实现同前 int main() { Clock c1(0, 0, 0); //调用有参数的构造函数 Clock c2; //调用无参数的构造函数 …… } 3.4 拷贝构造函数 拷贝构造函数的定义

motivation 复制构造函数是一种特殊的构造函数,其形参为本类的对象引用。作用是用一个已 存在的对象去初始化同类型的新对象。

class 类名 { public : 类名(形参);//构造函数 类名(const 类名 &对象名);//拷贝构造函数 // ... }; 类名::类( const 类名 &对象名)//拷贝构造函数的实现 采用引用的方式进行赋值 { 函数体 } 例 Point 类的完整程序 class Point { //Point 类的定义 public: Point(int xx=0, int yy=0) { x = xx; y = yy; } //构造函数,内联 Point(const Point& p); //复制构造函数 void setX(int xx) {x=xx;} void setY(int yy) {y=yy;} int getX() const { return x; } //常函数 int getY() const { return y; } //常函数 private: int x, y; //私有数据 }; //拷贝构造函数的实现 Point::Point (const Point& p) { x = p.x; y = p.y; cout Point a(1, 2); return a;} int main() { Point a(4, 5); Point b(a); //用a初始化b。 cout int sid; char name[200]; int age; }; struct Student st = {1001,"zhangsan",18};//整体赋值,类似于Java中new类的构造函数 st.id=1001;//单个赋值 strcpy(st.name,"zhangsan"); st.age=18; struct Student *pst = &st;//通常使用指针的方式赋值 //pst所指向的结构体变量中的sid这个成员 pst->sid=1001;//==(*pst).sid==st.sid strcpy(pst->name,"lisi"); pst->age=19;

结构体在定义一个对象后,系统为自定进行初始化,数值类型为0,字符类型为空。 • 注意事项 结构体变量不能算术计算,但是可以赋值;

两者相同点 结构体和类,其数据的默认值时相同的,对于数值型为0,对于字符型为空。其原理都是采用了默认构造函数,因此结构一也是可以用构造函数进行赋值的 typedef struct person{ char name[6]; int yy,mm,dd; person(){} person(int _yy,int _mm,int _dd){ yy = _yy; mm = _mm; dd = _dd; } }PER;

具体应用可以参考本人写的结构体应用博客:结构体应用解析

两者差别点 类是结构体的扩充,类不仅可以含有不同类型的数据,而且还可以有函数(操作行为);结构体仅仅只能表示各种不同类型的数据。类默认情况下是成员为私有类型成员,结构体默认情况下是公有类型成员 3.7 对象数组和对象指针 对象数组

对象数组的定义与访问

定义对象数组 类名 数组名[元素个数];访问对象数组元素 通过下标访问,数组名[下标].成员名

对象类数组初始化:

数组中每个元素对象被创建时,系统都会调用类构造函数初始化该对象。通过初始化列表赋值,如: Point a[2] = {Point(1,2),Point(3,4)};如果没有为数组元素制定显示初始值,数组元素边使用默认值初始化

数组元素所属类的构造函数

元素所属的类不声明构造函数,则采用默认构造函数。各元素对象的初值要求为相同的值时,可以声明具有默认形参值的构造函数。各元素对象的初值要求为不同的值时,需要声明带形参的构造函数。当数组中每一个对象被删除时,系统都要调用一次析构函数。 #include using namespace std; class Point { //类的定义 public: //外部接口 Point(); Point(int x, int y); ~Point(); void move(int newX,int newY); int getX() const { return x; } int getY() const { return y; } static void showCount(); //静态函数成员 private: //私有数据成员 int x, y; }; Point::Point() : x(0), y(0) { cout cout cout } int getX() const { return x; } int getY() const { return y; } private: int x, y; }; int main() { Point a(4, 5); Point *p1 = &a; //定义对象指针,用a的地址初始化 cout //构造函数 //在构造函数中对count累加,所有对象共同维护同一个count count++; } Point(Point &p) { //拷贝构造函数 x = p.x; y = p.y;count++; } ~Point() { count--; } int getX() { return x; } int getY() { return y; } void showCount() { //输出静态数据成员 cout public: Point(int x = 0, int y = 0) : x(x), y(y) { count++; }//构造函数 Point(Point &p) { //拷贝构造函数 x = p.x; y = p.y; count++; } ~Point() { count--; } int getX() { return x; } int getY() { return y; } static void showCount() { cout //Point类声明 public: //外部接口 Point(int x=0, int y=0) : x(x), y(y) { } int getX() { return x; } int getY() { return y; } friend float dist(Point &a, Point &b); private: //私有数据成员 int x, y; }; float dist( Point& a, Point& b) { double x = a.x - b.x; double y = a.y - b.y;return static_cast(sqrt(x * x + y * y)); } int main() { Point p1(1, 1), p2(4, 5); cout cout a.x=i; } void B::display() { a.display(); } 类的友元关系是单向的

如果声明B类是A类的友元,B类的成员函数就可以访问A类的私有和保护数据,但A 类的成员函数却不能访问B类的私有、保护数据。

3.10常类型 常对象

必须进行初始化,不能被更新。 const 类名 对象名

class A { public: A(int i,int j) {x=i; y=j;} ... private: int x,y; }; A const a(3,4); //a是常对象,不能被更新 常成员

用const进行修饰的类成员:常数据成员和常函数成员 常成员函数 - 使用const关键字说明的函数。 - 常成员函数不更新对象的数据成员。 - 常成员函数说明格式: 类型说明符 函数名(参数表)const; 这里,const是函数类型的一个组成部分,因此在实现部分也要带const关键 字。 - const关键字可以被用于参与对重载函数的区分

通过常对象只能调用它的常成员函数。

常数据成员

使用const说明的数据成员。 //常成员函数举例 #include using namespace std; class R { public: R(int r1, int r2) : r1(r1), r2(r2) { } void print(); void print() const; private: int r1, r2; }; void R::print() { cout R a(5,4); a.print(); //调用void print() const R b(20,52); b.print(); //调用void print() const return 0; } #include using namespace std; class A { public: A(int i); void print(); private: const int a; static const int b; //静态常数据成员 }; const int A::b=10; A::A(int i) : a(i) { } void A::print() { cout //Point类定义 public: //外部接口 Point(int x = 0, int y = 0): x(x), y(y) { } int getX() { return x; } int getY() { return y; } friend float dist(const Point &p1,const Point &p2); private: //私有数据成员 int x, y; }; float dist(const Point &p1, const Point &p2) { double x = p1.x - p2.x;double y = p1.y - p2.y; return static_cast(sqrt(x*x+y*y)); } int main() { //主函数 const Point myp1(1, 1), myp2(4, 5); cout string s1 = "DEF"; cout string city, state; getline(cin, city, ','); getline(cin, state); cout


【本文地址】

公司简介

联系我们

今日新闻

    推荐新闻

    专题文章
      CopyRight 2018-2019 实验室设备网 版权所有