C++程序设计(二)
1. 类
class CRectangle {
public:
int w, h;
void Init( int w_, int h_ ) {
w = w_; h = h_;
}
int Area() {
return w * h;
}
int Perimeter() {
* ( w + h );
}
}; //必须有分号
int main() {
int w, h;
CRectangle r; //r是一个对象
cin >> w >> h;
r.Init(w, h);
cout << r.Area() << endl << r. Perimeter();
;
}
类定义的变量 -> 类的实例 -> “对象”
对象的大小 = 所有成员变量的大小之和。E.g. CRectangle类的对象, sizeof(CRectangle) = 8
对象之间可以用 ‘=’ 进行赋值
- 访问类的成员变量和成员函数
用法1: 对象名.成员名CRectangle r1, r2; r1.w = ; r2.Init(,);
用法2: 指针->成员名
CRectangle r1, r2; CRectangle * p1 = & r1; CRectangle * p2 = & r2; p1->w = ; p2->Init(,); //Init作用在p2指向的对象上
用法3: 引用名.成员名
CRectangle r2; CRectangle & rr = r2; rr.w = ; rr.Init(,); //rr的值变了,r2的值也变
- 类的成员函数的另一种写法
class CRectangle { public: int w, h; int Area(); //成员函数仅在此处声明 int Perimeter() ; void Init( int w_, int h_ ); };int CRectangle::Area() { return w * h; } int CRectangle::Perimeter() { * ( w + h ); } void CRectangle::Init( int w, int h) { this->w = w; this->h = h;
}
2. 类成员的可访问范围
private: 指定私有成员, 只能在成员函数内被访问
public: 指定公有成员, 可以在任何地方被访问
protected:指定保护成员
缺省为私有成员!
对象成员的访问权限:
类的成员函数内部, 可以访问:当前对象的全部属性, 函数; 同类其它对象的全部属性, 函数
类的成员函数以外的地方只能够访问该类对象的公有成员
class CEmployee {
private:
]; //名字
public :
int salary; //工资
void setName(char * name);
void getName(char * name);
void averageSalary(CEmployee e1,CEmployee e2);
};
void CEmployee::setName( char * name) {
strcpy( szName, name); //ok
}
void CEmployee::getName( char * name) {
strcpy( name, szName); //ok
}
void CEmployee::averageSalary(CEmployee e1,CEmployee e2){
salary = (e1.salary + e2.salary )/;
}
int main(){
CEmployee e;
strcpy(e.szName,"Tom1234567889"); //编译错, 不能访问私有成员
e.setName( "Tom"); // ok
e.salary = ; //ok
;
}
设置私有成员的目的:强制对成员变量的访问一定要通过成员函数进行
设置私有成员的机制 -- 隐藏
2. 构造函数
成员函数的一种:
- 名字与类名相同,可以有参数,不能有返回值(void也不行)
- 作用是对对象进行初始化,如给成员变量赋初值
- 如果定义类时没写构造函数,则编译器生成一个默认的无参数的构造函数
- 默认构造函数无参数,不做任何操作
- 如果定义了构造函数,则编译器不生成默认的无参数的构造函数
- 对象生成时构造函数自动被调用。对象一旦生成,就再也不能在其上执行构造函数
- 一个类可以有多个构造函数,参数个数或类型不同
class Complex {
private :
double real, imag;
public:
void Set( double r, double i);
}; //编译器自动生成默认构造函数
Complex c1; //默认构造函数被调用
Complex * pc = new Complex; //默认构造函数被调用
class Complex {
private :
double real, imag;
public:
Complex( );
};
Complex::Complex( double r, double i) {
real = r; imag = i;
}
Complex c1; // error, 缺少构造函数的参数
Complex * pc = new Complex; // error, 没有参数
Complex c1(); // OK
Complex c1(,), c2(,);
Complex * pc = ,);
class Complex {
private :
double real, imag;
public:
void Set( double r, double i );
Complex(double r, double i );
Complex (double r );
Complex (Complex c1, Complex c2);
};
Complex::Complex(double r, double i) {
real = r; imag = i; }
Complex::Complex(double r){
real = r; imag = ;
}
Complex::Complex (Complex c1, Complex c2){
real = c1.real+c2.real;
imag = c1.imag+c2.imag;
}
Complex c1() , c2(,), c3(c1,c2);
构造函数在数组中使用
class CSample {
int x;
public:
CSample() {
cout << "Constructor 1 Called" << endl;
}
CSample(int n) {
x = n; cout << "Constructor 2 Called" << endl;
}
};
int main(){
CSample array1[];
cout << "step1"<<endl;
CSample array2[] = {,};
cout << "step2"<<endl;
CSample array3[] = {};
cout << "step3"<<endl;
CSample * array4 =
];
delete []array4;
;
}
输出: Constructor Called Constructor Called step1 Constructor Called Constructor Called step2 Constructor Called Constructor Called step3 Constructor Called Constructor Called
class Test {
public:
Test( int n) { } //(1)
Test( int n, int m) { } //(2)
Test() { } //(3)
};
Test array1[] = { , Test(,) };
// 三个元素分别用(1),(2),(3)初始化
Test array2[] = { Test(,), Test(,) , };
// 三个元素分别用(2),(2),(1)初始化
Test * pArray[] = { ), ,) };
//两个元素分别用(1),(2) 初始化
3. 内联成员函数
- inline + 成员函数
- 成员函数声明时便定义时,自动成为内联函数
4. 成员函数的重载及参数缺省
#include <iostream>
using namespace std;
class Location {
private :
int x, y;
public:
void init( int x = 0 , int y = 0 );
void valueX( int val ) { x = val ; }
int valueX() { return x; }
};
void Location::init( int X, int Y){
x = X;
y = Y;
}
int main() {
Location A;
A.init();
A.valueX();
cout << A.valueX();
;
}
4. 复制构造函数
- 只有一个参数,即对同类对象的引用。
- 形如 X::X( X& )或X::X(const X &), 二者选一,后者能以常量对象作为参数
- 如果没有定义复制构造函数,那么编译器生成默认复制构造函数。默认的复制构造函数完成复制功能。
- 如果定义的自己的复制构造函数, 则默认的复制构造函数不存在。
class Complex {
public :
double real,imag;
Complex(){ }
Complex( const Complex & c ) {
real = c.real;
imag = c.imag;
cout << “Copy Constructor called”; }
};
Complex c1;
Complex c2(c1);//调用自己定义的复制构造函数,输出 Copy Constructor called
复制构造函数起作用的三种情况
1)当用一个对象去初始化同类的另一个对象时。
2)如果某函数有一个参数是类 A 的对象, 那么该函数被调用时,类A的复制构造函数将被调用。
3) 如果函数的返回值是类A的对象时,则函数返回时,A的复制构造函数被调用.
5. 类型转换构造函数
目的:实现类型的自动转换
特点:只有一个参数,不是复制构造函数
当使用类型转换构造函数的时候,编译器会自动调用这个转换构造函数,建立一个临时对象/临时变量。
class Complex {
public:
double real, imag;
Complex( int i ) { //类型转换构造函数
cout << “IntConstructor called” << endl;
real = i; imag = ;
}
Complex( double r, double i ){
real = r;
imag = i; }
};
int main () {
Complex c1(, );
Complex c2 = ;
c1 = ; // 9被自动转换成一个临时Complex对象
cout << c1.real << "," << c1.imag << endl;
;
}
6. 析构函数
成员函数的一种
- 名字与类名相同,在前面加‘~’
- 没有参数和返回值
- 一个类最多只有一个析构函数
- 对象消亡时被自动调用
- 定义类时没写析构函数, 则编译器生成缺省析构函数(不涉及释放用户申请的内存释放等清理工作)
定义了析构函数, 则编译器不生成缺省析构函数
// 对象数组生命期结束时, 对象数组的每个元素的析构函数都会被调用
class Ctest {
public:
~Ctest() { cout<< "destructor called" << endl; }
};
int main () {
Ctest array[];
cout << "End Main" << endl;
;
}
delete 运算导致析构函数调用 Ctest * pTest; pTest = new Ctest; //构造函数调用 delete pTest; //析构函数调用 ------------------------------------------------------------------ pTest = ]; //构造函数调用3次 delete [] pTest; //析构函数调用3次
构造函数和析构函数 调用时机的例题
class Demo {
int id;
public:
Demo( int i ){
id = i;
cout << “id=” << id << “ Constructed” << endl;
}
~Demo(){
cout << “id=” << id << “ Destructed” << endl;
}
};
输出:
Demo d1(); id=1 Constructed
void Func(){ id=4 Constructed
); id=6 Constructed
Demo d3(); id=6 Destructed
cout << “Func” << endl; main
} id=5 Constructed
int main (){ id=5 Destructed
Demo d4(); id=2 Constructed
d4 = ; id=3 Constructed
cout << “main” << endl; Func
{ Demo d5(); } id=3 Destructed
Func(); main ends
cout << “main ends” << endl; id=6 Destructed
; id=2 Destructed
} id=1 Destructed
7. 静态成员变量和静态成员函数
静态成员:在说明前面加了static关键字的成员。
class CRectangle {
private:
int w, h;
static int nTotalArea; //静态成员变量
static int nTotalNumber;
public:
CRectangle(int w_,int h_);
~CRectangle();
static void PrintTotal(); //静态成员函数
};
普通成员变量每个对象有各自的一份,而静态成员变量一共就一份,为所有对象共享。
- sizeof 运算符不会计算静态成员变量。
- 普通成员变量每个对象有各自的一份,而静态成员变量一共就一份,为所有对象共享。
- 普通成员函数必须具体作用于某个对象,而静态成员函数并不具体作用与某个对象。因此静态成员不需要通过对象就能访问。
- 静态成员变量本质上是全局变量,哪怕一个对象都不存在,类的静态成员变量也存在。静态成员函数本质上是全局函数。
- 在静态成员函数中,不能访问非静态成员变量, 也不能调用非静态成员函数。
class CRectangle
{
private:
int w, h;
static int nTotalArea;
static int nTotalNumber;
public:
CRectangle(int w_,int h_);
~CRectangle();
static void PrintTotal();
};
CRectangle::CRectangle(int w_,int h_) {
w = w_; h = h_; nTotalNumber ++; nTotalArea += w * h;
}
CRectangle :: CRectangle(CRectangle & r ) {
w = r.w; h = r.h; nTotalNumber ++; nTotalArea += w * h;
}
CRectangle::~CRectangle() {
nTotalNumber --; nTotalArea -= w * h;
}
void CRectangle::PrintTotal() {
cout << nTotalNumber << "," << nTotalArea << endl;
}
;
;
// 必须在定义类的文件中对静态成员变量进行一次说明或初始化。否则编译能通过,链接不能通过。
int main(){
CRectangle r1(,), r2(,);
//cout << CRectangle::nTotalNumber; // Wrong , 私有
CRectangle::PrintTotal();
r1.PrintTotal();
;
}
输出结果: , ,
8. 成员对象和封闭类
成员对象: 一个类的成员变量是另一个类的对象,包含 成员对象 的类叫 封闭类 (Enclosing)
class CTyre { //轮胎类
private:
int radius; //半径
int width; //宽度
public:
CTyre(int r, int w):radius(r), width(w) { }
};
class CEngine { //引擎类
};
class CCar { //汽车类 “封闭类”
private:
int price; //价格
CTyre tyre;
CEngine engine;
public:
CCar(int p, int tr, int tw);
};
CCar::CCar(int p, int tr, int w):price(p), tyre(tr, w){ };
int main(){
CCar car(,,);
;
}
定义封闭类的构造函数时, 添加初始化列表:
类名::构造函数(参数表):成员变量1(参数表), 成员变量2(参数表), …
{
…
}
调用顺序
当封闭类对象生成时,
•S1: 执行所有成员对象 的构造函数
•S2: 执行 封闭类 的构造函数
成员对象的构造函数调用顺序
•和成员对象在类中的声明顺序一致
•与在成员初始化列表中出现的顺序无关
当封闭类的对象消亡时,
•S1: 先执行 封闭类 的析构函数
•S2: 执行 成员对象 的析构函数
析构函数顺序和构造函数的调用顺序相反
class CTyre {
public:
CTyre() { cout << "CTyre contructor" << endl; }
~CTyre() { cout << "CTyre destructor" << endl; }
};
class CEngine {
public:
CEngine() { cout << "CEngine contructor" << endl; }
~CEngine() { cout << "CEngine destructor" << endl; }
};
class CCar {
private:
CEngine engine;
CTyre tyre;
public:
CCar( ) { cout << “CCar contructor” << endl; }
~CCar() { cout << "CCar destructor" << endl; }
};
int main(){
CCar car;
;
}
程序的输出结果是: CEngine contructor CTyre contructor CCar contructor CCar destructor CTyre destructor CEngine destructor
9. 友元
一个类的友元函数可以访问该类的私有成员
class CCar; //提前声明 CCar类, 以便后面CDriver类使用
class CDriver {
public:
void ModifyCar( CCar * pCar) ; //改装汽车
};
class CCar {
private:
int price;
friend int MostExpensiveCar( CCar cars[], int total); //声明友元
friend void CDriver::ModifyCar(CCar * pCar); //声明友元
};
void CDriver::ModifyCar( CCar * pCar)
{
pCar->price += ; //汽车改装后价值增加
}
int MostExpensiveCar( CCar cars[], int total) //求最贵汽车的价格
{
;
; i < total; ++i )
if( cars[i].price > tmpMax)
tmpMax = cars[i].price;
return tmpMax;
}
int main(){
;
}
将一个类的成员函数(包括构造, 析构函数)声明为另一个类的友元
class B {
public:
void function();
};
class A {
friend void B::function();
};
A是B的友元类 则A的成员函数可以访问B的私有成员
class CCar {
private:
int price;
friend class CDriver; //声明CDriver为友元类
};
class CDriver {
public:
CCar myCar;
void ModifyCar() { //改装汽车
myCar.price += ; // CDriver是CCar的友元类可以访问其私有成员
}
};
int main() {
;
}
注意:友元类之间的关系不能传递, 不能继承
10. this指针

其作用就是指向成员函数所作用 的对象。
非静态成员函数中可以直接使用this来代表指向该函数作用的对象的指针。
class Complex {
public:
double real, imag;
void Print() { cout << real << "," << imag ; }
Complex(double r,double i):real(r),imag(i){ }
Complex AddOne() {
this->real ++; //等价于 real ++;
this->Print(); //等价于 Print
return * this;
}
};
int main() {
Complex c1(,),c2(,);
c2 = c1.AddOne();
;
} //输出 2,1


静态成员函数中不能使用 this 指针!
因为静态成员函数并不具体作用与某个对象!
因此,静态成员函数的真实的参数的个数,就是程序中写出的参数个数!
C++程序设计(二)的更多相关文章
- JavaScript高级程序设计(二):在HTML中使用JavaScript
一.使用<script>元素 1.<script>元素定义了6个属性: async:可选.表示应该立即下载脚本,但不应该妨碍页面中的其他操作,比如下载其他资源或等待加载其他脚本 ...
- python基础16 ----面向对象程序设计二
一.继承与派生 1.继承的定义:继承是一种创建新类的方式,即在类中提取共同的部分创建出一个类,这样的类称为父类,也可称为基类和超类,新建的类称为派生类或子类. 2.单继承:就相当于子类继承了一个父类. ...
- CUDA程序设计(二)
算法设计:直方图统计 直方图频数统计,也可以看成一个字典Hash计数.用处不是很多,但是涉及CUDA核心操作:全局内存.共享内存.原子函数. 1.1 基本串行算法 这只是一个C语言练习题. #def ...
- javascript 高级程序设计 二
这里我们直接进入主题: 在JS刚刚开始的时候,必须面临一个问题,那就是如何使的JS的加载和执行不会影响web核心语言HTML的展示效果,和HTML和谐共存. 在这个背景下<script>标 ...
- 实验7 shell程序设计二(1)
编写一个shell过程完成如下功能(必须在脚本中使用函数)1.程序接收3个参数:$1/$2和$3,合并两个文件$1/$2为$3,并显示,三个文件均为文本文件.2.如果文件$3不存在,那么先报告缺少$3 ...
- Linux命令(十一)——Shell程序设计二(循环控制语句)
1.if语句 (1)两路分支的if语句 (2)多路条件判断分支的if语句 2.测试语句 (1)文件测试 (2)字符串测试 (3)数值测试 (4)用逻辑操作符进行组合的测试语句 3.case语句 4.f ...
- 周会材料:高并发程序设计<二>
第三章 JDK并发包https://www.cnblogs.com/sean-zeng/p/11957569.html JDK内部提供了大量实用的API和框架.本章主要介绍这些JDK内部功能,主要分为 ...
- 2017-2018-2 20165206 实验二《Java面向对象程序设计》实验报告
2017-2018-2 20165206 实验二<Java面向对象程序设计>实验报告 一.实验报告封面 课程:Java程序设计 班级:1652班 姓名:韩啸 学号:20165206 指导教 ...
- 20165323 实验二 Java面向对象程序设计
一.实验报告封面 课程:Java程序设计 班级:1653班 姓名:杨金川 学号:20165323 指导教师:娄嘉鹏 实验日期:2018年4月16日 实验时间:13:45 - 15:25 实验序号:二 ...
- Java 多线程程序设计
课程 Java面向对象程序设计 一.实验目的 掌握多线程程序设计 二.实验环境 1.微型计算机一台 2.WINDOWS操作系统,Java SDK,Eclipse开发环境 三.实验内容 1.Java有 ...
随机推荐
- ASP.net的url重写
http://blog.csdn.net/windok2004/article/details/2432691 1. 有关于URL的重写,本文也只是拿来主意.相继有MS的组件“URLRewriter” ...
- (转)HBase工程师线上工作经验总结----HBase常见问题及分析
阅读本文可以带着下面问题:1.HBase遇到问题,可以从几方面解决问题?2.HBase个别请求为什么很慢?你认为是什么原因?3.客户端读写请求为什么大量出错?该从哪方面来分析?4.大量服务端excep ...
- Hadoop核心组件
1.Hadoop生态系统 2.HDFS(Hadoop分布式文件系统) 源自于Google的GFS论文,发表于2003年10月,HDFS是GFS克隆版. 是Hadoop体系中数据存储管理的基础.它是一个 ...
- 【BZOJ】1104: [POI2007]洪水pow
题意 给一个\(n * m(1 \le n, m \le 1000)\)的矩阵,如果\(a_{i, j}\)为正表示城市.\(|a_{i, j}|(|a_{i, j}| \le 1000)\)是格子\ ...
- HDU 4597 Play Game
题目链接 什么都不想说,最近状态暴跌.. #include <cstdio> #include <cstring> #include <iostream> usin ...
- Flex与.net进行URL参数传递编码处理
在JS中用到的三种编码方式escape 对应于Flex中是一样的,并且支持相互的解码 var a:String = "超越梦想#"; trace(escape(a)); //%u8 ...
- jQuery常用方法验证
验证邮箱: $('input[data-name="email"]').keyup(function () { var em; em = $(this).val(); if (!e ...
- 详解C#break ,continue, return
C#编程语法中break ,continue, return这三个常用的关键字的学习对于我们编程开发是十分有用的,那么本文就向你介绍break ,continue, return具体的语法规范. C# ...
- android中versionCode&versionName
原文来自:http://blog.csdn.net/wh_19910525/article/details/8660416 ,略有修改 一.概述 Android的版本可以在androidmainfes ...
- [CareerCup] 16.1 Thread and Process 线程和进程
16.1 What's the difference between a thread and a process? 进程Process是程序执行时的一个实例.一个进程是被分配系统资源的独立单元,每个 ...