快乐学C++: 对象的初始化
摘要:
本文避开面向对象的理论,简单讲述面向对象的由来,并通过代码和对代码结果的分析,阐述了面向对象中的重要的概念:对象的初始化。
对象和面向对象的由来:
在
C++
面向对象编程中,最重要的概念莫过于“对象”了。简单的说,对象就是把数据和对数据的操作进行抽象和封装形成的用户自定义的数据类型。
C++
提供了简单的基本数据类型,如整型,字符型,浮点型,还提供了对这些基本类型的简单复合,如数组,字符数组,及字符串;
C++
还提供了用户自定义的结构体,枚举类型。
在引入面向对象编程之前,程序员思考问题的方法对已知的问题一步一步进行分解,直至问题小得可以通过数据结构加算法来描述。这种思想方法一般称为面向过程的编程思想。面向过程解决需求明确,规范小的软件还可以,当面复杂的行业应用,有大量的应用领域的专门业务逻辑的规则的时候,程序员就面临着巨大的挑战,这个挑战就是程序员不得不面对具体的数据和对数据操作的细节。往往程序员并不是应用领域的专家,所以处理这些业务逻辑并不擅长,比如,某个程序员要编写保险行业的软件,保险行业本身的业务规则就非常复杂,因此程序员在大型软件的开发上所以很容易就败下阵来。
20
世80年代,曾经有统计,高达
70%
的软件不能在预算内如期完成。
人们呼唤换作思想来开发软件,这种思想就是面向对象。面向对象的核心思想就是把数据隐藏起来形成新的数据类型,只提供访问这些数据的接口,只要接口满足预期的目的,使用这些对象的程序员就不必关心接口内部的实现细节。面向对象有一个重要的原则,就是面向接口编程。
对象的实现
本文的上一节把面向对象“吹”得神忽其神,那么,在
c++
中,什么是对象,对象怎么创建,对象的接口怎么访问,对象怎么销毁呢?
请看下面的代码和代码的运行结果。我们重点演示了对象的初始化。
请注意对象的下面几个重要函数:
构造函数;
带参数的构造函数
;
拷贝构造函数;
赋值函数;
析构函数。
这些概念请同学们自己从教科书上查看详细解释,按照本系列文章的惯例,我们通过代码来理解上述函数。
代码和运行结果
main.cpp
- //file: main.cpp
- #include "square.h"
- #include <iostream>
- using namespace std;
- Square_T g_s(9);
- int main (int , char *[])
- {
- cout << "main start here" << endl;
- cout << "a: ";
- Square_T a;
- a.draw();
- cout << "b: ";
- Square_T b (5);
- b.draw();
- {
- cout << "inner b: ";
- Square_T b (5);
- b.draw();
- }
- cout << " c: ";
- Square_T c = b;
- c.draw();
- cout << " d: ";
- Square_T d (b);
- d.draw();
- d.side(10);
- cout << " d: ";
- Square_T e;
- e = d;
- e.draw();
- // Square_T f = 20;
- // f.draw();
- cout << "create object dynamically" << endl;
- Square_T* h = new Square_T(30);
- h->draw();
- delete h;
- h = 0;
- cout << " begin of array "<< endl;
- {
- Square_T many[5];
- }
- cout << "end of array "<< endl;
- cout << "main end here" << endl;
- return 0;
- }
Square.h
- //file : square.h
- #ifndef SQUARE_H
- #define SQUARE_H
- class Square_T
- {
- public:
- Square_T ();
- explicit Square_T (int side);
- Square_T (const Square_T & a);
- Square_T & operator = (const Square_T & a);
- virtual ~Square_T ();
- virtual int draw();
- void side( int sideLength);
- int side() const ;
- // 求面积
- int area();
- // 求周长
- int circumference();
- private:
- int side_;
- };
- #endif
Square.cpp
- //file: square.cpp
- #include <iostream>
- using namespace std;
- #include "square.h"
- Square_T ::Square_T ()
- :side_(0)
- {
- cout << "call: default constructor function " << endl;
- }
- Square_T::Square_T(int side)
- : side_(side)
- {
- cout << "call: constructor with parameter (side =" << side_ << " )" << endl;
- }
- Square_T ::Square_T (const Square_T & a)
- :side_(a.side_)
- {
- cout << "call: copy constructor function (a.side =" << a.side_ << " )" << endl;
- }
- Square_T& Square_T::operator = (const Square_T& a)
- {
- cout << "call : assigement function " << endl;
- if (this != &a)
- {
- this->side_ = a.side_;
- }
- return *this;
- }
- Square_T::~Square_T()
- {
- cout << "call : destructor function , side = " << this->side_ << endl;
- }
- int Square_T::draw()
- {
- cout << "square, side " << this->side_ << endl;
- return 0;
- }
- void Square_T::side(int side)
- {
- this->side_ = side;
- }
- int Square_T::side() const
- {
- return this->side_;
- }
- int Square_T::area()
- {
- return this->side_ * this->side_;
- }
- int Square_T::circumference()
- {
- return 4 * this->side_;
- }
运行结果
- call: constructor with parameter (side =9 )
- main start here
- a: call: default constructor function
- square, side 0
- b: call: constructor with parameter (side =5 )
- square, side 5
- inner b: call: constructor with parameter (side =5 )
- square, side 5
- call : destructor function , side = 5
- c: call: copy constructor function (a.side =5 )
- square, side 5
- d: call: copy constructor function (a.side =5 )
- square, side 5
- d: call: default constructor function
- call : assigement function
- square, side 10
- create object dynamically
- call: constructor with parameter (side =30 )
- square, side 30
- call : destructor function , side = 30
- begin of array
- call: default constructor function
- call: default constructor function
- call: default constructor function
- call: default constructor function
- call: default constructor function
- call : destructor function , side = 0
- call : destructor function , side = 0
- call : destructor function , side = 0
- call : destructor function , side = 0
- call : destructor function , side = 0
- end of array
- main end here
- call : destructor function , side = 10
- call : destructor function , side = 10
- call : destructor function , side = 5
- call : destructor function , side = 5
- call : destructor function , side = 0
- call : destructor function , side = 9
补充说明
请注意:
1.
全局变量
(side=9)
的初始化会早于
main
开始,销毁要晚于
main
结束。
2.
请注意
C++
关键字
explicit
的运行,它可以防止将一个整数转换成
Square_T
对象。即
Square_T f = 20;
或 f = 20; 编译时就报错,阻止这种不正当的行为。
3.
注意不同变量的作用域,查看析构函数的调用时机。