欣乐

The eagles are coming!

导航

第十二章 类

 

 

code:

 

 

/*


第三部分 类和数据抽象


第12章 类
12.1 类的定义和声明
12.2 隐含的this指针
12.3 类作用域
12.4 构造函数
12.5 友元
12.6 static类成员
小结




第三部分 类和数据抽象
第12章 类 367
12.1 类的定义和声明 368
12.1.1 类定义:扼要重述 368
12.1.2 数据抽象和封装 369
12.1.3 关于类定义的更多内容 372
12.1.4 类声明与类定义 374
12.1.5 类对象 375
12.2 隐含的this指针 376
12.3 类作用域 380
类作用域中的名字查找 382
12.4 构造函数 385
12.4.1 构造函数初始化式 387
12.4.2 默认实参与构造函数 391
12.4.3 默认构造函数 392
12.4.4 隐式类类型转换 393
12.4.5 类成员的显式初始化 396
12.5 友元 396
12.6 static类成员 398
12.6.1 static成员函数 400
12.6.2 static数据成员 400
小结 403
术语 403


*/



// 12.1 类的定义和声明 -------------------------------------------------------------------------------------------------

// in book
#include <iostream>
#include <sstream>
#include <string>
#include <vector>
#include <list>
#include <algorithm>
#include <iterator>
using namespace std;

class Sales_item
{
  public:
    // operations on Sales_item objects
    double avg_price()const;
    bool same_isbn(const Sales_item &rhs)const
    {
        return isbn == rhs.isbn;
    }
    // default constructor needed to initialize members of built-in type
    Sales_item(): units_sold(0), revenue(0.0){} // 构造函数初始化列表
  private:
    std::string isbn;
    unsigned units_sold;
    double revenue;
};

double Sales_item::avg_price()const
{
  if(units_sold)
    return revenue / units_sold;
  else
    return 0;
}

int main()
{
  return 0;
}


// test this
#include <iostream>
#include <sstream>
#include <string>
#include <vector>
#include <list>
#include <algorithm>
#include <iterator>
using namespace std;

class Sales_item
{
  public:
    // operations on Sales_item objects
    double avg_price() const;
    bool same_isbn(const Sales_item &rhs) const
    {
        return this->isbn == rhs.isbn; //
    }
    // default constructor needed to initialize members of built-in type
    Sales_item(): units_sold(0), revenue(0.0){} // 构造函数初始化列表
  private:
    std::string isbn;
    unsigned units_sold;
    double revenue;
};

double Sales_item::avg_price() const // const 成员函数不能改变其所操作的对象的数据成员
{
  if(this->units_sold)
    return this->threvenue / this->units_sold; //
  else
    return 0;
}

int main()
{
  return 0;
}



#include <iostream>
#include <string>
using namespace std;

class Screen
{
  public:
    // interface member functions
  private:
    std::string contents;
    std::string::size_type cursor;
    std::string::size_type height, width;
};

int main()
{
  return 0;
}


// typedef
#include <iostream>
#include <string>
using namespace std;

class Screen
{
  public:
    // interface member functions
  private:
    std::string contents;
    std::string::size_type cursor;
    std::string::size_type height, width;
};

class Screen2
{
  public:
    // interface member functions
    typedef std::string::size_type index;
  private:
    std::string contents;
    index cursor;
    index height, width;
};

int main()
{
  return 0;
}


// 函数重载
#include <iostream>
#include <string>
using namespace std;
class Screen
{
  public:
    typedef std::string::size_type index;
    // return character at the cursor or at a given position
    char get()const
    {
        return contents[cursor];
    } 
    char get(index ht, index wd)const;
    // remaining members
  private:
    std::string contents;
    index cursor;
    index height, width;
};

char Screen::get(index h, index w) const
{
  return( 't' ); // just for test
}

int main()
{
  Screen myscreen;
  char ch = myscreen.get(); // calls Screen::get()
  ch = myscreen.get(0, 0); // calls Screen::get(index, index)
  return 0;
}



// inline
#include <iostream>
#include <string>
using namespace std;

class Screen
{
  public:
    typedef std::string::size_type index;
    // implicitly inline when defined inside the class declaration
    char get()const
    {
        return contents[cursor];
    }
    // explicitly declared as inline; will be defined outside the class declaration
    inline char get(index ht, index wd)const;
    // inline not specified in class declaration, but can be defined inline later
    index get_cursor()const;
  private:
    std::string contents;
    index cursor;
    index height, width;
};

// inline declared in the class declaration; no need to repeat on the definition
char Screen::get(index r, index c)const
{
  index row = r * width; // compute the row location
  return contents[row + c]; // offset by c to fetch specified character
}

// not declared as inline in the class declaration, but ok to make inline in definition
inline Screen::index Screen::get_cursor()const  // 定义类型的成员,如 Screen::index,使用作用域操作符来访问。
{
  return cursor;
}

int main()
{
  class Screen myscreen; // class 经常不写
  char ch = myscreen.get(); // calls Screen::get()
  ch = myscreen.get(0, 0); // calls Screen::get(index, index)
  return 0;
}


// 12.2 隐含的this指针 -------------------------------------------------------------------------------------------------

// this
#include <iostream>
#include <string>
using namespace std;

class Screen
{
  public:
    typedef std::string::size_type index;
    // interface member functions
    Screen &move(index r, index c);
    Screen &set(char);
    Screen &set(index, index, char);
    // other members as before
  private:
    std::string contents;
    index cursor;
    index height, width;
};

Screen &Screen::set(char c)
{
  contents[cursor] = c;
  return  *this;
}

Screen &Screen::move(index r, index c)
{
  index row = r * width; // row location
  cursor = row + c;
  return  *this;
}

int main()
{
  class Screen myScreen;
  myScreen.move(4,0).set('#');

  return 0;
}



// 基于 const 的重载

#include <iostream>
#include <string>
using namespace std;

class Screen
{
  public:
    typedef std::string::size_type index;
    // interface member functions
    Screen &move(index r, index c);
    Screen &set(char);
    Screen &set(index, index, char);
    //Screen(): height(0), width(0){} // 构造函数初始化列表 //
    //Screen( index i, index j ) { height=i; width=j; }  // 加这两句
    Screen(index i,index j):height(i),width(j){} // 也可以这样构造初始化列表
    // display overloaded on whether the object is const or not
    Screen& display(std::ostream &os)
      { do_display(os); return *this; }
    const Screen& display(std::ostream &os) const
      { do_display(os); return *this; }
  private:
    void do_display(std::ostream &os) const
      { os << contents; }
    std::string contents;
    index cursor;
    index height, width;
};

Screen &Screen::set(char c)
{
  contents[cursor] = c;
  return  *this;
}

Screen &Screen::move(index r, index c)
{
  index row = r * width; // row location
  cursor = row + c;
  return  *this;
}

int main()
{
  Screen myScreen(5,3);
  const Screen blank(5, 3);
  myScreen.set('#').display(cout); // calls nonconst version
  blank.display(cout);             // calls const version

  return 0;
}


// 可变数据成员
#include <iostream>
#include <string>
using namespace std;

class Screen
{
  public:
    typedef std::string::size_type index;
    Screen &move(index r, index c);
    Screen &set(char);
    Screen &set(index, index, char);
    Screen(index i,index j):height(i),width(j){}
    Screen& display(std::ostream &os)
      { do_display(os); return *this; }
    const Screen& display(std::ostream &os) const
      { do_display(os); return *this; }
  private:
    void do_display(std::ostream &os) const
    { 
      ++access_ctr; // keep count of calls to any member function
      os << contents; 
    }
    mutable size_t access_ctr; // 可变数据成员 may change in a const members    
    std::string contents;
    index cursor;
    index height, width;
};

Screen &Screen::set(char c)
{
  contents[cursor] = c;
  return  *this;
}

Screen &Screen::move(index r, index c)
{
  index row = r * width; // row location
  cursor = row + c;
  return  *this;
}

int main()
{
  Screen myScreen(5,3);
  const Screen blank(5, 3);
  myScreen.set('#').display(cout); // calls nonconst version
  blank.display(cout);             // calls const version

  return 0;
}



// 12.3 类作用域 -------------------------------------------------------------------------------------------------

#include <iostream>
#include <string>
using namespace std;

class First
{
  public:
    int memi;
    double memd;
};

class Second
{
  public:
    int memi;
    double memd;
};

int main()
{
  First obj1;
  // Second obj2 = obj1; // error: obj1 and obj2 have different types
  return 0;
}



#include <iostream>
#include <string>
using namespace std;

class First
{
  public:
    int memi;
    double memd;
    void tempf(){ cout << "test" << endl; }
};

int main()
{
  First obj;
  First *ptr = &obj;
  ptr->memi;
  obj.memi;
  ptr->tempf();
  obj.tempf();
  
  return 0;
}



// 类作用域中的名字查找

#include <iostream>
#include <string>
using namespace std;

int i(43);

class First
{
  public:
    int memi;
    double memd;
    void tempf(){ cout << i << endl; } // 贯穿。全局变量一样贯穿进去
};


int main()
{
  First obj;
  First *ptr = &obj;
  ptr->tempf();
  obj.tempf();
  
  return 0;
}




// 12.4 构造函数 -------------------------------------------------------------------------------------------------


// 实参决定使用哪个构造函数

#include <iostream>
#include <string>
using namespace std;

class Sales_item
{
    // other members as before
  public:
    // added constructors to initialize from a string or an istream
    Sales_item(const std::string &){cout << "string" << endl; };
    Sales_item(std::istream &){cout << "istream" << endl; };
    Sales_item(){ cout << "nothing" << endl; }; // just for test
};

int main()
{
  // uses the default constructor:
  // isbn is the empty string; units_soldand revenue are 0
  Sales_item empty;
  // specifies an explicit isbn; units_soldand revenue are 0
  Sales_item Primer_3rd_Ed("0-201-82470-1");
  // reads values from the standard input into isbn, units_sold, and revenue
  Sales_item Primer_4th_ed(cin);
  
  return 0;
}


// 并非所有类成员都会默认初始化——内置类型的成员不进行隐式初始化
// **没有默认构造函数的类类型的成员,以及 const 或引用类型的成员,不管是哪种类型,都必须在构造函数初始化列表中进行初始化。**
#include <iostream>
#include <string>
using namespace std;

class First
{
  public:
    int i;
    double d;
    string s; // 已经初始化为 empty tring
};

int main()
{
  First obj;
  First *ptr = &obj;
  cout << ptr->i << endl; // 基本数据类型没有初始化
  cout << ptr->s << endl;
  cout << ptr->d << endl;
  
  return 0;
}




//下面的构造函数是错误的:

#include <iostream>
#include <string>
using namespace std;

class ConstRef
{
  public:
    ConstRef(int ii);
  private:
    int i;
    const int ci;
    int &ri;
};

// no explicit constructor initializer: error ri is uninitialized
ConstRef::ConstRef(int ii)
{
  // assignments:
  i = ii; // ok
  ci = ii; // error: cannot assign to a const
  ri = i; // assigns to ri which was not bound to an object
}

int main()
{
  ConstRef refobj(42);

  return 0;
}


/*
记住,可以初始化 const 对象或引用类型的对象,但不能对它们赋值。在开始执行构造函数的函数体之前,要完成初始化。
初始化 const 或引用类型数据成员的唯一机会是构造函数初始化列表中。
必须对任何 const 或引用类型成员以及没有默认构造函数的类类型的任何成员使用初始化式。
*/

#include <iostream>
#include <string>
using namespace std;

class ConstRef
{
  public:
    // ok: explicitly initialize reference and const members
     ConstRef::ConstRef(int ii): i(ii), ci(i), ri(ii) { }
  private:
    int i;
    const int ci;
    int &ri;
};

int main()
{
  ConstRef refobj(42);

  return 0;
}



/*
构造函数初始化列表仅指定用于初始化成员的值,并不指定这些初始化执行的次序。
成员被初始化的次序就是定义成员的次序。
所有会有警告:warning: 'X::j' will be initialized after

按照与成员声明一致的次序编写构造函数初始化列表是个好主意。此外,尽可能避免使用成员来初始化其他成员。

*/

#include <iostream>
#include <string>
using namespace std;

class X
{
    int i;
    int j;
  public:
    // run-time error: i is initialized before j
    X(int val): j(val), i(j){} // 实际上是按定义的顺序。。即先i,再j
};

int main()
{
  X refobj(42);
  return 0;
}



// 12.5 友元 -------------------------------------------------------------------------------------------------

// 12.6 static类成员 -------------------------------------------------------------------------------------------------


// 书中只提供代码片断,要补全,比较坑爹。。总算编译成功。。
#include <iostream>
#include <string>
using namespace std;

class Account
{
  public:
    // interface functions here
    void applyint(){ amount += amount * interestRate; }
    static double rate() { return interestRate; }
    static void rate(double); // sets a new rate
  private:
    string owner;
    double amount;
    static double interestRate;
    static double initRate();
};

void Account::rate(double newRate)
{
  interestRate = newRate; // sets a new rate
}

double Account::initRate() // for interestRate
{
  return(3.14/100);
}

double Account::interestRate = initRate(); // only once

int main()
{
  Account ac1;
  Account *ac2 = &ac1;
  double rate;
  rate = ac1.rate(); // through an Account object or reference
  rate = ac2->rate(); // through a pointer to an Account object
  rate = Account::rate(); // directly from the class using the scope operator

  return 0;
}

 

 

 

 

TOP

 

posted on 2014-11-10 20:19  欣乐  阅读(164)  评论(0编辑  收藏  举报