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. 访问类的成员变量和成员函数
    用法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的值也变
  2. 类的成员函数的另一种写法
    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++程序设计(二)的更多相关文章

  1. JavaScript高级程序设计(二):在HTML中使用JavaScript

    一.使用<script>元素 1.<script>元素定义了6个属性: async:可选.表示应该立即下载脚本,但不应该妨碍页面中的其他操作,比如下载其他资源或等待加载其他脚本 ...

  2. python基础16 ----面向对象程序设计二

    一.继承与派生 1.继承的定义:继承是一种创建新类的方式,即在类中提取共同的部分创建出一个类,这样的类称为父类,也可称为基类和超类,新建的类称为派生类或子类. 2.单继承:就相当于子类继承了一个父类. ...

  3. CUDA程序设计(二)

    算法设计:直方图统计 直方图频数统计,也可以看成一个字典Hash计数.用处不是很多,但是涉及CUDA核心操作:全局内存.共享内存.原子函数. 1.1  基本串行算法 这只是一个C语言练习题. #def ...

  4. javascript 高级程序设计 二

    这里我们直接进入主题: 在JS刚刚开始的时候,必须面临一个问题,那就是如何使的JS的加载和执行不会影响web核心语言HTML的展示效果,和HTML和谐共存. 在这个背景下<script>标 ...

  5. 实验7 shell程序设计二(1)

    编写一个shell过程完成如下功能(必须在脚本中使用函数)1.程序接收3个参数:$1/$2和$3,合并两个文件$1/$2为$3,并显示,三个文件均为文本文件.2.如果文件$3不存在,那么先报告缺少$3 ...

  6. Linux命令(十一)——Shell程序设计二(循环控制语句)

    1.if语句 (1)两路分支的if语句 (2)多路条件判断分支的if语句 2.测试语句 (1)文件测试 (2)字符串测试 (3)数值测试 (4)用逻辑操作符进行组合的测试语句 3.case语句 4.f ...

  7. 周会材料:高并发程序设计<二>

    第三章 JDK并发包https://www.cnblogs.com/sean-zeng/p/11957569.html JDK内部提供了大量实用的API和框架.本章主要介绍这些JDK内部功能,主要分为 ...

  8. 2017-2018-2 20165206 实验二《Java面向对象程序设计》实验报告

    2017-2018-2 20165206 实验二<Java面向对象程序设计>实验报告 一.实验报告封面 课程:Java程序设计 班级:1652班 姓名:韩啸 学号:20165206 指导教 ...

  9. 20165323 实验二 Java面向对象程序设计

    一.实验报告封面 课程:Java程序设计 班级:1653班 姓名:杨金川 学号:20165323 指导教师:娄嘉鹏 实验日期:2018年4月16日 实验时间:13:45 - 15:25 实验序号:二 ...

  10. Java 多线程程序设计

    课程  Java面向对象程序设计 一.实验目的 掌握多线程程序设计 二.实验环境 1.微型计算机一台 2.WINDOWS操作系统,Java SDK,Eclipse开发环境 三.实验内容 1.Java有 ...

随机推荐

  1. 在windows和linux下如何查看80端口占用情况?是被哪个进程占用?如何终止等

    一.在windows下如何查看80端口占用情况?是被哪个进程占用?如何终止等 这里主要是用到windows下的DOS工具,点击"开始"--"运行",输入&quo ...

  2. HDU 2851 (最短路)

    题目链接:http://acm.hdu.edu.cn/showproblem.php?pid=2851 题目大意:给出N条路径,M个终点(是路径的编号) .重合的路径才算连通的,且路径是单向的.每条路 ...

  3. android 内部缓存器(手机自带的存储空间中的当前包文件的路径)

    关于Context中: 1. getCacheDir()方法用于获取/data/data/<application package>/cache目录 2. getFilesDir()方法用 ...

  4. 自己收集原生js-2014-2-15

    function testforbtn(event){ alert(window.EventUtil.getEventTarget(window.EventUtil.getEvent( event)) ...

  5. hdu1232 并查集

    1. hdu1232 2.链接:http://acm.hdu.edu.cn/showproblem.php?pid=1232 3.总结:简单并查集 #include<iostream> # ...

  6. FS210开发板上Qt4.7.0移植过程

    作者:冯老师,华清远见嵌入式学院讲师. 1. 搭建Qt开发环境平台 1.开发环境:ubuntu 12.04 2.交叉编译链:arm-cortex_a8-linux-gnueabi 3.开发板:FS21 ...

  7. 20145330《Java程序设计》第四周学习总结

    20145330<Java程序设计>第四周学习总结 一周两章新知识的自学与理解真的是很考验和锻炼我们,也对前面几章我们的学习进行了检测,遇到忘记和不懂的知识就再复习前面的,如此巩固也让我对 ...

  8. CentOS转的服务器磁盘规划

    我的服务器是500G.最重要的是/var分区一定要大(不论postfix邮件,还是LAMP的WEB 服务器等).最好是400G以上.具体的/boot 只要100M就足够了.下面是我的分区方案:硬盘50 ...

  9. php 实现推技术comet(转)

    实现实时通信一般有两种方式:socket或comet.socket是比较好的解决方案,问题在于不是所有的浏览器都兼容,服务器端实现起来也稍微有点麻烦.相比之下,comet(基于HTTP长连接的&quo ...

  10. Maven3路程(一)用Maven创建第一个web项目(2)

    工具/原料 Windows 系统 JDK 1.5 及以上版本 Maven 3.0 及以上版本 方法/步骤 1 首先检查Eclipse是否已经添加的Maven插件,打开Eclipse, 依次选择 &qu ...