c++(下)中国农业大学学习笔记1

面向对象程序设计之一

长方形类
类实现放在 .cpp中
int Rectangle::area()//命名空间 ::作用域声明符
{
return longwidth;//在类实现中 数据成员long width相当于全局变量 函数成员可以直接访问
}
int Rectangle::len()
{
return (2
(a+b));
}

class Rectangle//类声明 放在.h中
{
public:
int long;
int width;//类变量
int area();//函数成员
int len();
};

public公有成员是封装后类对外的接口
一个类必须有公有成员

private私有成员 只能在类中被调用

分类和封装

1.cpp
类声明
class Rectangle
{
public:
int long;
int width;//类变量
int area();//函数成员
int len();
};

int Rectangle::area()//命名空间 ::作用域声明符
{
return longwidth;//在类实现中 数据成员long width相当于全局变量 函数成员可以直接访问
}
int Rectangle::len()
{
return (2
(a+b));
}

可以写在同一.cpp中先声明再实现

其他.cpp文件要用这个类时需先声明 需先将类声明代码拷贝在调用前
2.cpp
class Rectangle
{
public:
int long;
int width;//类变量
int area();//函数成员
int len();
};

int main()
{
Rectangle obj1;

}
为避免拷贝声明的问题一般把声明放在1.h中在2.cpp要用时直接include"1.h" 类实现(函数)还是放在1.cpp

include"1.h"
int main()
{
Rectangle obj1;

}

封装 可重用代码
类的封装 开放(被外部访问),隐藏(只在类内部访问)
访问权限
public 公有权限 被赋予公有权限的类是开放的 称为公有成员
private 私有权限 被赋予私有权限的类成员将被隐藏
protected 保护权限 被赋予保护权限的类成员是半开放的

头文件 2.h
class Cirle
{
private :
double r;
double CArea();
double Clen();
public:
void Input();
void Show();
}
2.cpp
对成员变量及函数的实现
1.cpp
#include"2.h"
int main()
{
Cirle obj1;
obj1.Input();
obj1.Show();
}

类的接口
公有成员是封装后类对外的接口
一个类必须有公有成员 否则这个类无法使用

任务 长方形与两个圆形每面积造价10 测算工程总造价
分析 主函数 输入长宽和半径,计算造价,输出
抽象 长方形类 圆形类 属性成员和方法成员
class Cirle//声明 在.h中
{
public:
double r;
double CArea();
}
//实现 在.cpp中
double Cirle::CArea()//::为作用域声明符
{return 3.14rr*10;}
组装
int main()
{
Cirle obj1,obj2;
Rectangle obj3;
cin>>obj1.r>>obj2.r;
double all;
all+=obj1.CArea();
all+=obj2.CArea();
cout<<all<<endl;
return 0;
}

类的定义
class 类名
{//成员声明 但不能初始化
public:
//公有成员
protected:
//保护成员
private:
//私有成员
};
各成员的完整定义//类实现在声明的大括号之外
声明时需要在函数名前加 “类名::”
函数成员可以访问本类中任意位置的数据成员或调用本类中任意位置的函数成员
不受权限约束在声明和实现两部分中 类成员具有类作用域
不同类作用域之间的类的成员之间可以重名

Class abc
{
int do;//未指定访问权限时默认为private
public :
float d1;
void fun1();
protected :
bool d2;
void fun2();

private:
char d3;
int fun3();
};
//类实现
void Abc::fun1(){…}

数据成员的语法
数据成员也称为属性是类中的变量用于保存数据
数据成员的类型可以是基本数据类型也可以是自定义数据类型
数据成员不能与其他成员重名
声明数据成员的语法形式类似于定义变量 所不同的是声明数据成员不能初始化

函数成员的语法
函数成员也称为方法
函数成员可以直接访问本类中的数据成员 数据成员相当于是类中的全局变量
函数成员可以直接调用本类中的其它函数成员
在类中声明函数成员时可以指定形参的默认值
不同函数成员之间可以重名即重载函数 两个函数的形参个数不同或数据类型不同那么
这两个函数就可以重载 函数成员不能与数据成员重名
可以将函数成员定义为内联函数,在类实现部分函数成员时可以使用inline关键字
将其定义成内联函数 或者直接将该函数成员实现在类声明部分的大括号中 c++编译器默认
将在类声明部分实现的函数成员当作内联函数处理

对象的定义和访问
定义对象 Cirle obj1;//圆形类对象的定义
对象拥有该类的全部成员
访问对象就是通过接口(公有成员)操作内存中的对象
对象中的公有成员可以访问,非公有成员(私有成员,保护成员)不能访问
访问对象名.成员
对象指针
Rectangle obj2,p;
p=&obj2;//可以指向已经定义好的类
(p).a 也可以 p->a 两者等价 通过对象指针也只能访问公有成员
类代码的编译
调整前
double Cirle::CArea()//::为作用域声明符
{return 3.14
r
r10;}
编译器调整后
double Cirle::CArea(Cirle
const this)//::为作用域声明符
{return 3.14this->rthos->r10;}
this指向本类的对象指针 const表示这是指针常变量在函数里this指针的指向不能被修改
const int x与int const x没有区别
涉及到指针
const int a=&b;//1
int const a=&b;//2
int
const a=&b;//3
const int
const a=&b;//4
如果const位于
号左侧const就是用来修饰指针所指的变量 即指针指向常量
const位于右侧const就是修饰指针本身 即指针本身是常量
1,2相同意义都是指针所指向的内容的类型为常量 这种情况下不允许对指针指向的内容做修改如不能
a=3
3指针本身是常量不允许改变指针的指向如a++但指针指向的内容不为常量
4指针本身和指针的指向内容都为常量
一个对象占用的内存空间为其类中所有数据成员所需的内存空间的总和
声明 Cirle obj1;
Rectangle obj2;
内存空间中 数据变量所占用的内存空间
obj1.r obj1
obj2.a obj2
obj2.b obj2
调用对象函数成员语句的编译
Cirle obj1;
obj1.Input();
//编译器调整后 Input(&obj1);
//void Cirle::Input(Cirle* const this)
//多个同类对象 共用函数方法代码内存中只用保存一份代码 降低内存占用

对象的构造与析构(解构)
变量在内存中的生存期
全局变量,局部变量,静态变量
全局变量,静态变量在生成后就一直存在直到程序结束
局部变量自动分配内存 直到其代码块结束释放内存

动态分配 new,delete
全局对象,局部对象,静态对象
构造函数 参与对象的构造过程(初始化) 当执行定义对象的语句时自动执行构造函数
特殊函数成员 构造函数名与类名相名
构造函数由计算机自动调用 程序员不能直接调用
构造函数通过形参传递初始值(可指定默认形参值)实现对新建对象数据成员的初始化
构造函数可以重载即定义多个同名的构造函数 这样可提供多种形式的对象构造方法
构造函数可以定义为内敛函数 直接实现在函数的声明部分
构造函数没有返回值 定义时不能写函数类型写void也不行
构造函数通常是类外调用 其访问权限应设为public或protected不能设为private
一个类如果没有定义构造函数编译器编译时将自动添一个空的构造函数称为默认构造函数
形式为 类名(){}

构造函数初始化对象
Cirle::Cirle(double x)//带形参的构造函数
{r=x;}
Cirle::Cirle()//不带形参的构造函数
{r=0;}
Cirle::Cirle(double x=0)
{r=x;}
用一个以存在的对象初始化当前新的对象
Cirle::Cirle(Cirle&obj)//引用
{r=obj.r;}
称为拷贝构造函数

显示对象的构造的过程
这样能让程序员便于检查代码中的错误
Cirle::Cirle(double x=0)
{r=x;cout<<“Cirle(double x=0)被调用”<<endl;}

构造函数申请额外内存
class Student
{
public:
char Name[9],ID[11];
int age;
double Score;
Student(char* pName,char* pID
,int iniage,double iniScore)//内联构造函数
{
strcpy(Name,pName);strcpy(ID,pID0);//初始化名字学号
age=iniage;Score=iniScore;
}

};
增加备注成员 charMemo可有可无有长有短
在构造函数中动态分配内存给这个Memo
Student(char
pName,char* pID
,int iniage,double iniScore
,char* pMemo)//内联构造函数
{
strcpy(Name,pName);strcpy(ID,pID0);//初始化名字学号
age=iniage;Score=iniScore;
int len=strlen(pMemo);//计算实际传递来的备注信息长度
if(len<=0)Memo=0;//没有备注信息 0表空指针NULL
else
{
Memo=new char[len+1];//按照实际长度分配内存 +1是因为结束的空字符?
strcpy(Memo,pMemo);//初始化备注信息
}
}
在构造函数中动态分配的内存new需要程序员编写析构函数来释放内存
类定义中添加析构函数 计算机在销毁对象时将自动调用析构函数
析构函数名必须为~类名
析构函数由计算机自动调用 程序员不能直接调用
析构函数没有形参
析构函数没有返回值定义时不能写函数类型void也不行
一个类只能有一个析构函数
析构函数通常是类外调用其访问权限应设为public或protected不能设为private
一个类如果没有定义析构函数 编译器在编译时将自动添加一个空的析构函数
默认析构函数~类名(){}

析构函数
清理内存
设置与当前对象相关的系统状态
~Student()
{
if(Memo!=0)delete[]Memo;
}

拷贝构造函数中的深拷贝和浅拷贝
当类中没有定义拷贝构造函数
Student.obj2(obj1);//将自动调用拷贝构造函数
将实参对象的数据成员一一对应拷贝给obj2
Student(Student &obj)
{
strcpy(Name,obj.Name);strcpy(ID,obj.ID);
age=obj.age; Score=obj.Score;
Memo=obj.Memo;//拷贝备注信息指针 注 并没有再分配内存
}
obj1和obj2的Memo指针指向的是同一块内存空间
类似于引用叫浅拷贝
深拷贝 拷贝的只是指针中的信息obj1和obj2的Memo指针指向的是不同内存空间
要深拷贝需要自己重写拷贝构造函数
Student(Student &obj)
{
strcpy(Name,obj.Name);strcpy(ID,obj.ID);
age=obj.age; Score=obj.Score;
//Memo=obj.Memo;//拷贝备注信息指针 注 并没有再分配内存
if(len<=0)Memo=0;//没有备注信息 0表空指针NULL
else
{
Memo=new char[len+1];//按照实际长度分配内存 +1是因为结束符’\0’
strcpy(Memo,obj.Memo);//拷贝备注信息
}
}

类与对象编程的主要内容
定义类 要考虑数据成员,函数成员,各成员的访问权限,构造函数和析构函数

定义对象 将类当作一种自定义数据类型来定义变量

访问对象 就是通过接口 即公有成员操作内存中的对象

//银行账户类
account.h
class Account
{
private:
int no;//
char name[10];
float money;
public:
void Depodit();//存款
void Withdraw();//取款
void show();//显示余额
Account::Account(int iniNo,char* iniName,float iniMoney);
};
account.cpp
#include “account.h”
void Account::Depodit()
{
cout<<“存多少”;
float x;cin>>x;
money+=x;
show();
}
void Account::Withdraw()
{
cout<<“取多少”;
float x;cin>>x;
if(money<x)cout<<“余额不足”;
else money-=x;
show();
}
void Account::show()//显示余额
{
cout<<money;
}

构造函数
Account::Account(int iniNo,char* iniName,float iniMoney)
{
no=iniNo;strcpy(name,iniName);money=iniMoney;
}

对象的应用
对象数组 保存多个对象
class square
{
public:
double a;//保存边长
double Area()//求正方形面积 内联函数
{return (a*a);}
square(double x=0)//带默认形参的构造函数,内联函数
{a=x;}
};

int main()
{
square obj[3]={square(2),square(3),square(4)};
//square obj[3]={square(2),square(3)};
//数组中有多少个元素(3)就会调用多少次构造函数 obj[2]未传递实参会自动调用默认值0 所以为Square(0)
//访问
cout<<obj[n].a;
Square* p=&obj[n];
cout<a;
//析构 有多少个数组元素就会调用多少次析构函数

//new delete对象的动态分配
Square*p;
p=new Square;//分配单个对象 返回空间首地址

delete p;
p=new Square(2);//可用构造函数 动态分配对象时会自动调用构造函数
//删除对象时也会自动调用析构函数

//动态分配对象数组
Squarep;
p=new Square[3];//有多少个元素(3)就会调用多少次构造函数
p[0].a=2;//
(p+0).a=2
(p+1)->a=3;//(p+1).a=3
p[0].Area();(p+1)->Area();

delete[]p;//有多少个元素(3)就会调用多少个析构函数
}
对象作为函数的形参
double innercircleArea(Square s)//求正方形内切圆面积
{
double r=s.a/2;
return 3.1415
r*r;
}
int main()
{
Square obj(10);
cout<<innercircleArea(obj);
形实结合相当于执行了Square s(obj);//相当于调用了一次默认拷贝构造函数

常对象 初始化后不能修改其数据成员
const Square obj(2);
cout<<obj.a;//可读取
obj.a=5;//错误

}
double innercircleArea(const Square s)//常对象形参值传递
{
//

}

值传递相当于要构造一个对象形参 要花费时间和空间
相比较而言引用传递和指针传递更高效

引用传递与常引用
double innercircleArea(Square& s)//求正方形内切圆面积
{
double r=s.a/2;
return 3.1415rr;
}
cout<<innercircleArea(obj);//main 不变
对s的修改都会影响到obj 因为两个其实是相同的存储空间就是同一个量
double innercircleArea(const Square& s)
//常引用 任何通过s间接修改obj数据成员的操作都是错误的

指针传递与指向常对象的指针
double innercircleArea( Squares)
{
double r=s->a/2;
return 3.1415
r*r;
}
cout<<innercircleArea(&obj);//main

double innercircleArea(const Square*s)//指向常对象的指针
任何通过s间接修改obj数据成员的操作都是错误的

被调函数不需要修改主调函数传递过来的对象而只是读取其中数据 则形参改为const类型

const数据保护机制
只使用而不修改的情况下 使用const保护数据成员不被修改
static 静态机制
延长局部变量的生存期 使全局变量或函数的作用域限定在本文件之内

常数据成员 常数只能在初始化时赋值然后不能再改 数据成员不能在定义时直接初始化
构造函数也不行 为构造函数添加初始化列表是对常数据成员初始化的唯一途径
构造函数名(形参列表):常数据成员名1(形参1),常数据成员名2(形参2)…
{

}
class Cirle{
public:
Cirle():pi(3.1415926),e(2.71828){}//构造声明
void dsp(){
cout << pi << ’ ’ << e << endl;
}
private:
const double pi,e;
};
形参1,2是从形参列表中提取出来的并在初始化列表中进行二次传递

常函数成员
某个函数成员只需要读取类中的数据成员而不做修改赋值则可以定义为常函数成员
内联函数
double getcost()const{return 3.14rrprice;}//只读不修改则定义为const类型
非内联函数
double getcost()const;//声明
double Cirle::getcost()const//实现
{return 3.14
rrprice;}
常函数成员只能调用其它常函数成员 为了防止非const函数间接在常函数内部修改了某些数据成员
通过常对象只能调用其常函数成员 为了防止无const函数间接修改了常对象的数据成员
常对象就是数据成员不能修改的对象
除形参个数 类型之外 还可以用关键字const区分类中的重载函数

静态数据成员
面向对象程序设计建议将全局变量变为静态数据成员
private:static double price;//声明
//在类外定义(实现),初始化 定义时加类名::
double Cirle::price=10;
静态数据成员通常和函数成员定义(实现) 一起放在类实现部分
定义(实现)是不用加static定义(实现)时可以初始化
同类函数成员中访问静态数据成员直接使用其成员名访问 不受权限约束
在类外其它函数中访问 如主函数中访问静态数据成员需要以 类名::静态数据成员名 来访问
或通过任何一个该类对象以 对象名.静态数据成员 类外只能访问公有静态数据成员
生存期 和全局变量一样 静态数据成员是静态分配的 程序加载后立即分配内存 直到程序执行结束退出时才被释放
作用域 私有静态数据成员只能在类内访问 公有静态数据成员具有文件作用域 可通过类声明(.h)被其他任何文件访问

静态函数成员
调用全局变量的函数
只访问类中的静态数据成员或调用其它静态函数成员
static double getcost();//声明时加static限定 实现时不需再使用static
只访问类中的静态数据成员因为静态函数成员可以不定义对象直接调用而非静态数据成员只有在定义对象后才分配
内存空间
类中的其他函数成员可使用其函数名直接调用 类外调用需以类名::静态函数成员()形式来调用或对象名.静态函数成员 且只能是public
静态函数成员不能是内敛函数 因为编译器在编译时会调整内敛函数 此时所访问的静态数据成员可能还未初始化因此数据是不可靠的

类的友元
与访问权限相关
Class A
{
public:int x;
protected:int y;
private:int z;
A(int p1=0,int p2=0,int p3=0){x=p1;y=p2;z=p3;}//私有权限 构造函数
}
私有成员只能在类内使用

类外
void fun()
{
A obj(1,2,3);
cout<<obj.y;//错误 对象只能访问公有成员
cout<<obj.z;//错误 不能访问私有成员
}
友元函数
class 类名
{

friend 友元函数原型声明;
}
用friend关键字 声明语句可以放在大括号内的任意位置
该位置的访问权限与友元函数无关
友元函数是类外的其他函数不是类的成员
友元函数可以在其函数体内访问该类对象的所有成员不受权限约束

Class A
{
public:int x;
protected:int y;
private:int z;
A(int p1=0,int p2=0,int p3=0){x=p1;y=p2;z=p3;}
friend void B::fun();//fun是类B的函数
}
void fun()
{
A obj(1,2,3);
cout<<obj.y;//正确
cout<<obj.z;//正确
}

友元类
类B的所有函数成员都是类A的友元函数则称类B是类A的友元类
Class B
{

void fun(){}

}

class A
{

friend class B;//声明类B为类A的友元类
}
声明类B为类A的友元类后 类B的所有函数成员都可以访问类A中的所有成员(包括数据与方法)

友元关系是单向的 若A声明B是自己的友元并不意味着自己同时成为对方
的友元除非对方声明自己是他的友元

友元关系不能传递 B是A的友元 C是B的友元 这并不意味着A,C间存在友元关系
除非他们自己单独声明

  • 1
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
https://blog.csdn.net/qq_44036990/article/details/104330168?ops_request_misc=%257B%2522request%255Fid%2522%253A%2522162458824716780264041251%2522%252C%2522scm%2522%253A%252220140713.130102334.pc%255Fall.%2522%257D&request_id=162458824716780264041251&biz_id=0&utm_medium=distribute.pc_search_result.none-task-blog-2~all~first_rank_v2~rank_v29-1-104330168.pc_search_result_control_group&utm_term=C%2B%2B%E5%8D%95%E9%93%BE%E8%A1%A8%E6%98%AF%E4%B8%80%E7%A7%8D%E9%93%BE%E5%BC%8F%E5%AD%98%E5%8F%96%E7%9A%84%E6%95%B0%E6%8D%AE%E7%BB%93%E6%9E%84%EF%BC%8C%E7%94%A8%E4%B8%80%E7%BB%84%E5%9C%B0%E5%9D%80%E4%BB%BB%E6%84%8F%E7%9A%84%E5%AD%98%E5%82%A8%E5%8D%95%E5%85%83%E5%AD%98%E6%94%BE%E7%BA%BF%E6%80%A7%E8%A1%A8%E4%B8%AD%E7%9A%84%E6%95%B0%E6%8D%AE%E5%85%83%E7%B4%A0%E3%80%82%E9%93%BE%E8%A1%A8%E4%B8%AD%E7%9A%84%E6%95%B0%E6%8D%AE%E6%98%AF%E4%BB%A5%E7%BB%93%E7%82%B9%E6%9D%A5%E8%A1%A8%E7%A4%BA%E7%9A%84%EF%BC%8C%E6%AF%8F%E4%B8%AA%E7%BB%93%E7%82%B9%E7%9A%84%E6%9E%84%E6%88%90%EF%BC%9A%E5%85%83%E7%B4%A0%28%E6%95%B0%E6%8D%AE%E5%85%83%E7%B4%A0%E7%9A%84%E6%98%A0%E8%B1%A1%29%2B%E6%8C%87%E9%92%88%28%E6%8C%87%E7%A4%BA%E5%90%8E%E7%BB%A7%E5%85%83%E7%B4%A0%E5%AD%98%E5%82%A8%E4%BD%8D%E7%BD%AE%29%EF%BC%8C%E5%85%83%E7%B4%A0%E5%B0%B1%E6%98%AF%E5%AD%98%E5%82%A8%E6%95%B0%E6%8D%AE%E7%9A%84%E5%AD%98%E5%82%A8%E5%8D%95%E5%85%83%EF%BC%8C%E6%8C%87%E9%92%88%E5%B0%B1%E6%98%AF%E8%BF%9E%E6%8E%A5%E6%AF%8F%E4%B8%AA%E7%BB%93%E7%82%B9%E7%9A%84%E5%9C%B0%E5%9D%80%E6%95%B0%E6%8D%AE%E3%80%82%E5%A6%82%E4%B8%8B%E5%9B%BE%E6%89%80%E7%A4%BA%EF%BC%9A&spm=1018.2226.3001.4187

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值