【北京大学】程序设计实习 (C++版)第2周 类和对象初步

感谢【北京大学】程序设计实习 (C++版) 郭炜/刘家瑛老师老师的辛勤付出,花了一段时间整理课的内容

目录

第2周 类和对象初步

         2-1 面向对象程序设计方法

2-2面向对象程序设计语言发展过程

2-3从客观对象抽象出的例子

         2-4 类成员的可访问范围

2-5 内联函数和重载函数

2-6 构造函数


第2周 类和对象初步

2-1 面向对象程序设计方法

1结构化程序设计:
• 复杂的大问题 à 层层分解/模块化 à 若干子问题
• 自顶向下, 逐步求精

 

                                            

结构化程序设计的问题:

 

 

2 面向对象的程序设计

面向对象的程序设计方法
面向对象的程序 = 类 + 类 + … + 类
设计程序的过程 à 设计类的过程

                                

 

2-2面向对象程序设计语言发展过程

C++语言的历史:

1979年, AT&T实验室Dr. Bjarne Stroustrup开始发明开始的版本称为: C with Classes
1983年8月, 第一个C++实现投入使用
1983年10月, 正式命名为C++ (CPlusPlus)
1985年10月, Bjarne完成了经典巨著The C++ Programming Language (第一版)
C++标准的发展
1989年, C++2.0版发布
1994年, ANSI C++标准发布
1998年, ANSI和ISO联合发布 “C++98” 标准加入STL (Standard Template Library) – 泛型设计
2003年, ISO的C++标准委员会发布 “C++03” 标准
2005年, “Library Technical Report 1” (TR1) 技术报告发布

2011年9月, ISO标准委员会通过了新的C++标准 -- C++11

常用的C++编译器:
GCC
Visual C++ 10.0
Dev C++
Eclipse
Borland C++Builder

 

第一个面向对象语言:Simula
Simula
1967年, Ole-Johan Dahl
和Kristen Nygaard
发布Simula 67
• 提出了类(class)和子类(subclass)的概念
• 程序设计语言发展史上的一个重要的里程碑

Bjarne Stroustrup
• http://www2.research.att.com/~bs/
• AT&T Fellow, AT&T Labs - Research
• Distinguished Professor
• Holder of the College of Engineering Chair
Computer Science at Texas A&M University
• C++ Bible
• The C++ Programming Language (4th Edition)
• Addison-Wesley ISBN 978-0321563842. May 2013.
 

 

2-3从客观对象抽象出的例子

                                    

程序如:

class CRectangle {
public:
       int w, h;
       void Init( int w_, int h_ ) {
              w = w_; h = h_;
       }
       int Area() {
              return w * h;
       }
       int Perimeter() {
              return 2 * ( w + h );
       }
}; //必须有分号

 

int main() {
I      nt w, h;
       CRectangle r; //r是一个对象
       cin >> w >> h;
       r.Init(w, h);
       cout << r.Area() << endl << r. Perimeter();
       return 0;
}
类定义的变量 à 类的实例 à “对象”

对象的内存分配:
a.对象的内存空间
• 对象的大小 = 所有成员变量的大小之和
E.g. CRectangle类的对象, sizeof(CRectangle) = 8
b.每个对象各有自己的存储空间
• 一个对象的某个成员变量被改变, 不会影响到其他的对象

对象间的运算:
对象之间可以用 ‘=’ 进行赋值
不能用 ‘==’, ‘!=’, ‘>’, ‘<’, ‘>=’, ‘<=’进行比较
• 除非这些运算符经过了 “重载”

访问类的成员变量和成员函数
用法1: 对象名.成员名
       CRectangle r1, r2;
       r1.w = 5;
       r2.Init(3,4);

用法2: 指针->成员名
       CRectangle r1, r2;
       CRectangle * p1 = & r1;
       CRectangle * p2 = & r2;
       p1->w = 5;
       p2->Init(3,4); //Init作用在p2指向的对象上

用法3: 引用名.成员名
       CRectangle r2;
       CRectangle & rr = r2;
       rr.w = 5;
       rr.Init(3,4); //rr的值变了,r2的值也变

另一种输出结果的方式
void PrintRectangle(CRectangle & r) {
       cout << r.Area() << ","<< r.Perimeter();
}
CRectangle r3;
r3.Init(3,4);
PrintRectangle(r3);

 

类的成员函数的另一种写法
成员函数体和类的定义分开写
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() {
return 2 * ( w + h );
}
void CRectangle::Init( int w_, int h_ ) {
w = w_; h = h_;
}
调用通过: 对象 / 对象的指针 / 对象的引用

2-4 类成员的可访问范围

类成员的可访问范围
关键字 -- 类成员可被访问的范围
private: 指定私有成员, 只能在成员函数内被访问
public: 指定公有成员, 可以在任何地方被访问
protected: 指定保护成员
三种关键字出现的次数和先后次序都没有限制

 

     

 

分析:

szName à char szName[5]
如果szName不是私有, 需要修改全部:
strcpy(man1.szName, “Tom1234567889”);
如果将szName变为私有,
所有对 szName的访问都是通过成员函数来进行,
man1.setName( “Tom12345678909887”);

2-5 内联函数和重载函数

函数重载:(参数缺省情况)

         需要注意二义性;

         当函数名相同和参数列表相同,如果返回值的类型相同,则是函数重定义(错误)

                                        

                                    

2-6 构造函数

基本概念:

  1. 成员函数的一种
  2. 名字与类名相同,可以有参数,不能有返回值(void也不行)
  3. 作用是对对象进行初始化,如给成员变量赋初值
  4. 如果定义类时没写构造函数,则编译器生成一个默认的无参数的构造函数
  5. 默认构造函数无参数,不做任何操作
  6. 如果定义了构造函数,则编译器不生成默认的无参数的构造函数
  7. 对象生成时构造函数自动被调用。对象一旦生成,就再也不能在其上执行构造函数
  8. 一个类可以有多个构造函数
  9. 为什么需要构造函数:

构造函数执行必要的初始化工作,有了构造函数,就不必专门再写初始化函数,也不用担心忘记调用初始化函数。

有时对象没被初始化就使用,会导致程序出错。

程序示例:

class Complex {
         private :
                  double real, imag;
         public:
                  void Set( double r, double i);
}; //编译器自动生成默认构造函数
Complex c1; //默认构造函数被调用
Complex * pc = new Complex; //默认构造函数被调用

程序示例2:

class Complex {
         private :
                   double real, imag;
         public:
                  Complex( double r, double i = 0);
};
Complex::Complex( double r, double i) {
         real = r; imag = i;
}
Complex c1; // error, 缺少构造函数的参数
Complex * pc = new Complex; // error, 没有参数
Complex c1(2); // OK
Complex c1(2,4), c2(3,5);
Complex * pc = new Complex(3,4);

 

 

可以有多个构造函数,参数个数或类型不同
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 = 0;
}
Complex::Complex (Complex c1, Complex c2);
{
         real = c1.real+c2.real;
         imag = c1.imag+c2.imag;
}
Complex c1(3) , c2 (1,0), c3(c1,c2);
// c1 = {3, 0}, c2 = {1, 0}, c3 = {4, 0};

 

构造函数最好是public的, private构造函数不能直接用来初始化对象
class CSample{
         private:
                  CSample() {
                  }
};
int main(){
         CSample Obj; //err. 唯一构造函数是private
         return 0;
}

 

构造函数在数组中的使用:

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[2];
cout << "step1"<<endl;
CSample array2[2] = {4,5};
cout << "step2"<<endl;
CSample array3[2] = {3};
cout << "step3"<<endl;
CSample * array4 =
new CSample[2];
delete []array4;
return 0;
}
输出:
Constructor 1 Called
Constructor 1 Called
step1
Constructor 2 Called
Constructor 2 Called
step2
Constructor 2 Called
Constructor 1 Called
step3
Constructor 1 Called
Constructor 1 Called

class Test {
         public:
                   Test( int n) { }

                   Test( int n, int m) { }

                   Test() { }
};
Test array1[3] = { 1, Test(1,2) };
// 三个元素分别用(1),(2),(3)初始化
Test array2[3] = { Test(2,3), Test(1,2) , 1};
// 三个元素分别用(2),(2),(1)初始化
Test * pArray[3] = { new Test(4), new Test(1,2) };
//两个元素分别用(1),(2) 初始化

 

 

 

 

 

 

 

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值