第3章 Class and Object

构造函数

Guaranteed initialization with the constructor使用构造函数保证初始化

• If a class has a constructor, the compiler  automatically calls that constructor at the  point an object is created, before client  programmers can get their hands on the  object. 

• The name of the constructor is the same as  the name of the class.

构造函数:

1、没有返回类型

2、会被自动调用

Constructors with arguments有参构造函数

• The constructor can have arguments to allow  you to specify how an object is created, give it  initialization values, and so on.

Tree(int i) {…}
Tree t(12);

Constructor1.cpp

struct X{
  int i;
  X(int i);
  void prt();
};
X::X(int i){
  this -> i = i;
}
X::prt(){
  cout << i << endl;
}
int main(){
  X a; //无参构造,相当于a.X()
  X a(1);//有参构造,相当于a.X(1)
  X a=1; //变量初始化,相当于X a(1)
  int m(10);// 相当于 m = 1;
  a.prt();
}

想要i的值固定

struct X{
  int i = 100;
  X();
  void prt();
};
//X::X(){
//  i = 100;
//}
X::prt(){
  cout << i << endl;
}
int main(){
  X a; //无参构造,相当于a.X()
  a.prt();
}

//C++11会后才有这个特性:在成员变量定义的时候给初始值
//也可以采用构造函数的方式给成员变量赋初始值
X::X(){
  i = 100;
}

default意思:缺省;默认

缺省构造函数:没有参数的构造函数,可以是程序员定义的或者程序员没写时编译器提供的

普通构造函数:有参数的构造函数 X(int i);

如果没有无参构造函数,只有有参构造函数,则创建对象需要传入有参构造函数的参数

struct X{
  int i = 100;
  X(int i);
  void prt();
};
X::X(int i){
  this -> i = i;
}
X::prt(){
  cout << i << endl;
}
int main(){
  X a; //会报错
  X a(1);//需要传入参数
  a.prt();
}

如果没有定义有参构造函数,创建对象时就不能加参数

struct X{
  int i = 100;
  X();
  void prt();
};
X::X(){
  i = 100;
}
X::prt(){
  cout << i << endl;
}
int main(){
  X a; //正确
  X a(1);//会报错
  a.prt();
}
int main(){
  X b[10];//每个数组元素的i值为100
  //如果想给数组元素对象的成员变量赋值
  X b[10](7)//不对
  X b[10] ={1,2,3,4,5}//不对,因为只提供了5个值,数组元素一共有十个
}

The default constructor默认构造函数

• A default constructor is one that can be called with 

no arguments.

struct Y {
 float f; 
 int i; 
 Y(int a); 
};
Y y1[] = { Y(1), Y(2), Y(3) }; //OK,每个元素类型都是Y,没有给大小,根据大括号内动态决定
Y y2[2] = { Y(1) };//错误,大括号内只有一个,要有两个
Y y3[7];//不行,结构体内含有参构造函数,创建对象就必须传入参数
Y y4;//不行,因为结构体内含有参构造函数,创建对象就必须传入参数

“auto” default constructor

• If you have a constructor, the compiler ensures  that construction always happens.

• If (and only if) there are no constructors for a  class (struct or class), the compiler will  automatically create one for you.

The destructor析构函数

• In C++, cleanup is as important as initialization and is  therefore guaranteed with the destructor.

• The destructor is named after the name of the class 

with a leading tilde (~). The destructor never has any 

arguments.

struct Y { 
  public: 
 	 ~Y(); 
};
struct X{
  X(int i);
  void prt();
  ~X();
};
X::X(int i){
  this -> i = i;
}
X::prt(){
  cout << i << endl;
}
X::~X(){
  cout << "~X()" << i << endl;
}
int main(){
  X a(7); 
  X b(11);
  a.prt();
  b.prt();
}
/*
输出:
7
11
~X()11 // b的析构
~X()7 // a的析构
*/

先构造的后析构,因为可能后面的对象会用到前面的对象,所以先构造的不能先析构。

//代码复杂一些
int main(){
  X a(7); 
  {
  X b(11);
  }
  a.prt();
  //b.prt();
}
/*
输出:
~X()11 //b被析构,因为出了大括号这个生存期
7
~X()7 // a的析构
*/

说明析构发生在离开大括号的时候

Storage allocation

• The compiler allocates all the storage for a  scope at the opening brace of that scope. 

• The constructor call doesn’t happen until the sequence point where the object is defined.

Examlpe: Nojump.cpp

class X{
  private:
  	char* buf;
  public:
  	X(){buf = new char[1024];};
  	~X(){delete buf;}
}
X::X(){}
void f(int i){
  if(i < 10){
    goto jump1;
  }
  X x1;
  jump1;
  	switch(i){
      case 1:
        X x2;
        break;
      case 2:
        X x3;
        break;
    }
}
/*
如果i小于10,goto跳转到jump1,一旦进入到f函数,本地变量就被分配了空间,
但是此时x1的构造函数不会执行,程序结束时,由于析构函数找不到要delete的buf 
同理,switch的大括号规定了x2和x3的生命周期,一旦进入就给他们分配了空间,但由于case,x2或x3可能不会在对应的case下执行构造函数,最后析构的时候也会有问题。
解决方法:
1、不用goto
2、不用switch
*/

Aggregate initialization聚合体初始化

• int a[5] = { 1, 2, 3, 4, 5 }; 
• int b[6] = {5}; 
• int c[] = { 1, 2, 3, 4 }; 
– sizeof c / sizeof *c
• struct X { int i; float f; char c; }; 
– X x1 = { 1, 2.2, 'c' }; 
• X x2[3] = { {1, 1.1, 'a'}, {2, 2.2, 'b'} }; 
• struct Y { float f; int i; Y(int a); }; 
• Y y1[] = { Y(1), Y(2), Y(3) };

Defifinition of a class

• In C++, separated .h and .cpp files are used to define  one class.

• Class declaration and prototypes in that class are in  the header file (.h).

• All the bodies of these functions are in the source  file (.cpp).

compile unit

• The compiler sees only one .cpp file, and  generates .obj file。一个.cpp文件是一个编译单元,编译器在编译的时候只看见这一个.cpp文件

• The linker links all .obj into one executable  file

• To provide information about functions in  other .cpp files, use .h

The header fifiles

• If a function is declared in a header file, you  must include the header file everywhere the  function is used and where the function is  defined.

• If a class is declared in a header file, you must  include the header file everywhere the class is  used and where class member functions are  defined.

Header = interface

• The header is a contract (契约)between you and the 

user of your code. 

• The compile enforces the contract by  requiring you to declare all structures and  functions before they

Structure of C++ program

Declarations vs Defifinitions

• A .cpp file is a compile unit

• Only declarations are allowed to be in .h

• extern variables

• function prototypes

• class/struct declaration

#include

• #include is to insert the included file into  the .cpp file at where the #include statement  is.

• #include “xx.h”:first search in the current  directory, then the directories declared  somewhere

• #include <xx.h>:search in the specified  directories

• #include <xx>:same as #include <xx.h>

Standard header fifile structure

防止多次声明

#ifndef HEADER_FLAG 
#define HEADER_FLAG 
	// Type declaration here...
#endif // HEADER_FLAG

Tips for header

1. One class declaration per header file

2. Associated with one source file in the same 

prefix of file name.

3. The contents of a header file is surrounded  with #ifndef #define #endif

Clock display

Abstract

• Abstraction is the ability to ignore details of  parts to focus attention on a higher level of a  problem.

• Modularization is the process of dividing a  whole into well-defined parts, which can be  built and examined separately, and which  interact in well-defined ways.

Modularizing the clock display

NumberDisplay.h

#ifndef __NUMBER_DISPLAY__
#define __NUMBER_DISPLAY__

struct NumberDisplay{
  int value = 0;
  int limit = 0; //上界
  NumberDisPlay(int limit);
  int setValue(int value);
  int getValue();
  bool increase();
};

#endif

NumberDisplay.cpp

#include "NumberDisplay.h"

NumberDisplay::NumberDisPlay(int limit){
  this -> limit = limit;  
}

void NumberDisPlay::setValue(int value){
  this -> value = value;
}

int NumberDisPlay::getvalue(){
  return value;
}

bool NumberDisPlay::increase(){
  value++;
  if(value == limit){
    value = 0; //当值达到上限时,重新置零
    return true;
  }
  return false;
}

main.cpp

#include <iostream>
#include "NumberDisPlay"
using namespace std;

int main(){
  NumberDisPlay n(10);
  n.setValue(2);
  for(int i = 0; i < 15; i++){
    if(n.increase()){
      cout << "-------------" << endl;
    }
    cout << n.getValue() << endl;
  }
  return 0;
}
/*
输出:
3
4
5
6
7
8
9
------------------
0
1
2
3
4
5
6
7
*/

Clock.h

#ifndef __CLOCK_H__
#define __CLOCK_H__

#include "NumberDisPlay.h"

struct Clock{
  // NumberDisplay hour(24);编译会报错
  // NumberDisplay minute(60);
  //类内初始值只能放在花括号里,或放在等号右边,记住不能使用圆括号
  NumberDisplay hour=24;
  NumberDisplay minute=60;
  void dida();
  int getTime()
}

#endif

Clock.cpp

#include "Clock.h"

void Clock::dida(){
  if(minute.increase()){
    hour.increase();
  }  
}

int Clock::getTime(){
  return hour.getValue() *100 + minute.getValue(); 
}

main.cpp

#include <iostream>
#include "NumberDisPlay"
#include "Clock.h"

using namespace std;

int main(){
  // NumberDisPlay n(10);
  // n.setValue(2);
  // for(int i = 0; i < 15; i++){
  //   if(n.increase()){
  //     cout << "-------------" << endl;
  //   }
  //   cout << n.getValue() << endl;
  // }
  Clock clk;
  for(int i = 0; i < 123; i++){
    clk.dida();
    cout << clk.getTime() << endl;
  }
  return 0;
}

类内初始值只能放在花括号里,或放在等号右边,记住不能使用圆括号。

类外部创建对象时可以用圆括号,表示使用有参构造函数。

  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值