类 - 1【C++ Primer 学习笔记 - 第十二章】

class Sales_item
{
public:
        // const 跟在形参表之后,可将成员函数声明为常量(必须同时出现在声明和定义中,否则报错)
        // const 成员不能改变其所操作的对象的数据成员
	double avg_price() const;
	bool same_isbn(const Sales_item &rhs) const
	{
		return isbn == rhs.isbn;
	}

	// 构造函数
	Sales_item(): units_sold(0), revenue(0.0) {}
private:
	string isbn;
	unsigned units_sold;
	double revenue;
};


类成员:
构造函数:
成员函数:在类的内部,可以先声明成员函数,而不定义该函数。类的内部定义的函数,默认为 inline
                    在类的外部定义成员函数的时候,需要指明它们是在类的作用域中。格式如:Sales_item::avg_price


数据抽象和封装

数据抽象:依赖于接口和实现分离的一种编程技术。类的设计者关心其实现,而使用者,只需了解使用接口。
封装:执行细节不可见。
实际上,
类的数据抽象视图由 public 成员定义,程序所有部分皆可对其访问
类的封装,则通过 private 成员实现,不可直接访问
访问标号(public、private 等)
如果类是由 struct 关键字定义的,则:第一个访问标号之前的成员是共有的。(默认共有,public)
如果类是由 class 关键字定义的,则:第一个访问标号之前的成员是私有的。(默认私有,private)


class Screen
{
public:
	//使用类型别名
	typedef string::size_type index;

	// 成员函数的重载
	char get() const { return contents[cursor];}

	// 显示指定 inline 成员函数
	// 上面的 char get() 成员,实际上会自动作为 inline 处理
	// 编译器将试图在同一行内扩展该函数。
	// 下面的重载成员函数 char get(index ht, index wd) 则是显示指定 inline
	inline char get(index ht, index wd) const;
	index get_cursor() const;
private:
	string contents;	
	index cursor;
	index height, width;
};
// 注意,此处,形参中,直接使用 index
char Screen::get(index r, index c) const
{
	index row = r*width;
	return contents[row + c];
}

// 注意,此处,返回类型,使用 Screen::index
inline Screen::index Screen::get_cursor() const
{
	return cursor;
}


在一个给定的源文件中,一个类,只能被定义一次。
如果在多个文件中定义一个类,必须保证每个文件中的定义是完全相同的。
因此,通常将类的定义放在头文件中,通过引用头文件,来确保类的在多个文件中的一致。
而,如果头文件被一个源文件多次引用,可能导致该类被多次定义而报错,
为避免这一情况,可使用头文件保护符(header guard)

#ifndef SALESITEM_H
#define SALESITEM_H
// Definition of Sales_item class
#endif

可以先声明类,而不定义。可称为:前向声明(forward declaration)。通常用于编写互相依赖的类
只能以有限的方式使用。

class Screen; // 不完全类型(incompete type)


class Screen{};
class LinkScreen
{
	// 定义 Screen 类型的 window时,
	// 必须是在定义 Screen 之后。
	// 如果仅仅是声明了 Screen,则无法定义 Screen 类型的数据成员window
	Screen window;

	// 因为只有在类 LinkScreen 定义体完成后,才能定义该类型
	// 因此,类 LinkScreen 不能具有自身类型(LinkScreen)的数据成员
	// 但,此处,类名 LinkScreen 已经出现,可认为已经作了声明
	// 则:数据成员可以是指向自身类型的指针或引用
	LinkScreen *next;
	LinkScreen *prev;
};


类对象,定义一个类的同时,也是定义了一个类型。
之后,就可以定义该类型的对象。
定义对象时,将为其分配存储空间,但是,定义类型时,不会分配进行存储分配。


类的定义必须以分号结束
因为类定义之后,可以接一个对象定义列表。

class Screen{} a, b;  // 既定义了类,也定义了类的对象a,b   但此方法不可取。不便阅读

隐含的 this 指针
成员函数,具有一个附加的隐含形参,即:指向该类对象的一个指针,形参名:this。
常见的使用 this 指针的情况:需要返回,调用该函数的对象,的引用。

myScreen.move(4,0).set("#"); 
// 等效于以下2句,要实现这一功能,需要使用 this指针


myScreen.move(4,0);
myScreen.set("#");


class Screen
{
public:	
	typedef string::size_type index;

	Screen &move(index r, index c);
	Screen &set(char);
	Screen &set(index, index, char);
private:
	string contents;	
	index cursor;
	index height, width;
};
Screen &Screen::set(char c)
{
	contents[cursor] = c;
}

Screen &Screen::move(index r, index c)
{
	index row = r * width;
	cursor = row + c;

	// this 是一个指向非常量 Screen 的指针。
	// 同其他指针一样,可以进行解引用。
	return *this;
}


  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值