简单的来说,类就是定义了一个新的类型和一个新的作用域。每个类可以没有成员,也可以定义多个成员,成员可以是数据,函数或类型别名。而这些类的成员呢 可以是公有的(public),也可以是私有(private)的和受保护的(protected)。
Class Sales_item{
Public :
Double avg_price() const;
Bool same_isbn(const Sales_item &rhs) const{return isbn == rbs.isbn;}
//用一个构造函数初始化列表 来初始化对象的数据成员
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;
}
类背后蕴涵的基本思想是数据抽象和封装。
数据抽象就是将"接口"和"实现"实现分离的编程技术。封装则是将一项低层次的元素组合起来形成新的 高层次实体的技术。
数据抽象和封装提供了两个重要优点:1.避免类内部出现无意的,可能破坏对象状态的用户级错误。 2.随时间推移可以根据需求改变或缺陷报告来完善类的实现,而无须改变用户级代码。
Class Screen{
Public:
typedef std::string::size_type index;
Char get() const {return contents[cursor]; }
inline char get(index ht, index wd) const;
index get_cursor() const;
};
Char Screen::get(index r, index c) const
{
index row = r * width;
Return contents[row + c];
}
inline Screen::index Screen::get_cursor() const
{
Return cursor;
}
上述例子中 使用了函数成员的重载定义--->函数名相同 参数的类型和个数不同
inline-->在类内部定义的成员函数,如案例中的get() 将自动作为inline处理 当它们被调用时,编译器将试图在同一行呢扩展该函数 也可以显示的将成员函数声明为inline 如案例中的 inline char get(index ht, index wd) const; 一般在类的外部定义inline可以使得类比较容易阅读。
Class Screen;这样是定义了一个类;也就是定义了一个类型。定义了类型,就可以定义改类型的对象了。一般来说 定义类型时不进行存储分配。但是,当我们定义一个对象 Screen sen/calss Screen sen; 时编译器就会分配一个足以容纳Screen对象的存储空间。
类中的成员函数 例如Char get() 都具有一个附加的隐含形参,即指向该类对象的一个指针(this);尽管在成员函数内部显示引用this通常是不必要的,但有一种情况下必须这样做:当我们需要将一个对象作为整体引用而不是引用对象的一个成员时。
当成员函数为非const,this的类型是一个指向类类型的const指针(可以改变this所指向的值,但不能改变this所保存的地址)。 当成员函数为const类型时,this的类型是一个指向const类类型对象的const指针(既不能改变this所指向的对象 也不能改变this所保存的地址)。
Class Screen {
Public:
Private:
Mutable size_t access_ctr;
};
void Screen::do_display(std::ostream& os) const
{
++access_ctr;
os<<contents;
}
在上述代码中出现了一个新的新的单词 mutable--->如果我们希望类的数据成员(甚至在const函数成员内)可以修改。这可以通过将它们声明为 mutable来实现。可变的数据成员永远都不能为const,甚至当它是const对象的成员时也是如此。因此,const成员函数可以改变mutable成员。