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. ccc 模拟重力 正太分布

    ball.js cc.Class({ extends: cc.Component, properties: { x_vel:{ default:0 }, y_vel:{ default:0 }, gr ...

  2. BZOJ2159 : Crash 的文明世界

    $x^k=\sum_{i=1}^k Stirling2(k,i)\times i!\times C(x,i)$ 设$f[i][j]=\sum_{k=1}^n C(dist(i,k),j)$. 则可以利 ...

  3. ACM 另一种阶乘问题

    另一种阶乘问题 时间限制:3000 ms  |  内存限制:65535 KB 难度:1   描述 大家都知道阶乘这个概念,举个简单的例子:5!=1*2*3*4*5.现在我们引入一种新的阶乘概念,将原来 ...

  4. 移动开发流量省起来之Zepto

    一张图说明Zepto.js的优势:   jquery 1.x最新版284KB,压缩后94KB:jquery2.x最新版247KB,压缩后84KB:Zepto最新版54KB,压缩后9KB!!!   然后 ...

  5. javascript 函数及作用域总结介绍

    在js中使用函数注意三点: 1.函数被调用时,它是运行在他被声明时的语法环境中的: 2.函数自己无法运行,它总是被对象调用的,函数运行时,函数体内的this指针指向调用该函数的对象,如果调用函数时没有 ...

  6. 升级到EF6 两个注意事项

    1.依据MSDN的官方描述: In previous versions of EF the code was split between core libraries (primarily Syste ...

  7. Flex Flash Player回声消除的最佳方法

    Adobe Flash Player 已经成为音频和视频播放的非常流行的工具.实际上,目前大多数因特网视频均使用 Flash Player观看. Flash Player 通过将许多技术进行组合可以提 ...

  8. (JavaScript 2.0: The Complete Reference, Second Edition)javascript 2.0完全手册第二版 翻译说明

    1,译文中javascript简称js. 2,本人翻译时将信息提炼加工,保留主要信息,个别地方可能与原文有出入. 3,为督促自己学习Javascript,从今天起每天翻译一些,每天更新. 下面是文章每 ...

  9. pushState()、popstate事件配合ajax实现浏览器前进后退页面局部刷新

    最近研究pushState,看了网上的文章还是不怎么会用,于是自己摸索着理解使用,终于实现局部刷新同时前进后退. 首先说说pushState(),这个函数将当前的url等信息加入history堆栈中: ...

  10. github提交失败并报错java.io.IOException: Authentication failed:

    一.概述 我最近在写一个android的项目. 软件:android studio.Android studio VCS integration(插件) Android studio VCS inte ...