您的位置:首页 > 编程语言 > C语言/C++

C++ primer 第三章 标准库类型

2012-11-16 18:46 337 查看
本章主要讲了标准库类型,其中主要从以下几个方面进行了说明。
第一:命名空间的using声明:
第二:标准库string类型:定义和初始化(三种)、读写、getline/string重点
第三:标准库vector类型:定义和初始化、对象操作
第四:迭代器简介(不懂)
第五:标准库bitset类型(不懂)
小结:
①变量和基本类型等都是低级数据类型,标准库类型更为高级更为抽象。其中最为重要的为string和vector标准库类型。
②使用using声明可以在不需要加前缀namespace_name::情况下,一个using只能作用于一个命名空间成员。
③using std::cin; using std::cout; using std::endl; 后面程序中可以不写std::.
④getline函数用于读取整行,eg:while (getline(cin,line)) ^^^^^^^return 0;
⑤vector值初始化、对象操作(size)、添加元素、下标操作

class Sale_item
{
public:
// 隐式使用string 的默认构造函数初始化 isbn

Sale_item():price(0.0){}

Sale_item(const string &book):isbn(book), price(0.0){}

// 建议使用默认实参,将上述2个构造函数合并。如下:

// Sale_item(const string &book = ""):isbn(book), price(0.0){}

private:
string isbn;
double price;
};

class Sale_item
{
public:
// 隐式使用string 的默认构造函数初始化 isbn
Sale_item():price(0.0){}

Sale_item(const string &book):isbn(book), price(0.0){}

// 建议使用默认实参,将上述2个构造函数合并。如下:
// Sale_item(const string &book = ""):isbn(book), price(0.0){}
private:
string isbn;
double price;
};


合成的默认构造函数

如果,类没有定义构造函数,编译器将会自动生成一个默认的构造函数。

但是,如果已经定义过构造函数(哪怕只有1 个), 编译器就不会再生成默认构造函数。

理由:因为一个类,在某种情况下,需要控制对象的初始化,则,该类很可能在所有情况下都需要控制。

合成的默认构造函数,的初始化规则,与变量的初始化规则相同。

类类型,使用各自的默认构造函数,来初始化

内置、复合类型,如:指针、数组,只对定义在全局作用域中的对象才初始化,

定义局部作用域中,则,内置、复合类型不初始化,处于未定义状态。

类通常,都应该定义一个默认构造函数

假设:NoDefault ,是一个类,它具有接受一个 string 实参的构造函数,

这种情况下,编译器,不会生成默认构造函数。

于是,

1、当我定义一个类 A,具有 NoDefault 类型的成员,则,

A 的所有构造器,都必须通过传递一个初始 string 来初始化 NoDefault 类型的成员

2、当我定义一个类 A,具有 NoDefault 类型的成员,则,

编译器将不会生成 A 的默认构造器。只能自己显示定义

3、NoDefault 类型,不能用作动态分配数组的元素类型。

[cpp]
view plaincopyprint?

int *iArr = new
int[10];

// 上式可行,下式报错
NoDefault *arr = new NoDefault[10];

int *iArr = new int[10];

// 上式可行,下式报错
NoDefault *arr = new NoDefault[10];


4、NoDefault 类型的静态分配数组,也必须为每个元素提供显示的初始化

5、如果有保存 NoDefault 对象的容器,如:vector,

则,容器的构造函数,不仅要提供容器大小,也要提供元素初始化式。

[cpp]
view plaincopyprint?

// 这是一个函数声明,函数返回类型:Sales_item

Sales_item myObj();

//
Sales_item myObj2;

// 创建一个 Sales_item 对象,并用默认构造函数初始化

Sales_item myObj3 = new Sales_item();

// 这是一个函数声明,函数返回类型:Sales_item
Sales_item myObj();

//
Sales_item myObj2;

// 创建一个 Sales_item 对象,并用默认构造函数初始化
Sales_item myObj3 = new Sales_item();


隐式类型转换

[cpp]
view plaincopyprint?

class Sales_item

{
public:

Sales_item(const string &book =
""):isbn(book), units_sold(0), revenue(0.0){}

// explicit 只能用于,类内部的构造函数声明上,在类的定义体外部则不用重复它

explicit Sales_item(istream &is);

Sales_item();

bool same_isbn(Sales_item item)

{
return item.isbn == isbn;
}
private:
string isbn;
int units_sold;
double revenue;

};
// 错误: explicit 只能在类内部的构造函数声明上

explicit Sales_item::Sales_item(istream &is)

{
/* ... */
}

/* ... */
string null_book = "9-999-9999-9";

Sales_item item_a = Sales_item("1-111-1111-1");

// 以下会隐式调用构造函数,生成一个 Sales_item 对象,来进行比较

// 但这种隐式转换,未必是我们真正想要的。
// 为阻止这种隐式转换,可以在构造函数前,使用 explicit 关键字

item_a.same_isbn(null_book);

// 建议使用下面的方式,避免错误
item_a.same_isbn(Sales_item(null_book));

class Sales_item
{
public:

Sales_item(const string &book = ""):isbn(book), units_sold(0), revenue(0.0){}
// explicit 只能用于,类内部的构造函数声明上,在类的定义体外部则不用重复它
explicit Sales_item(istream &is);
Sales_item();

bool same_isbn(Sales_item item)
{
return item.isbn == isbn;
}
private:
string isbn;
int units_sold;
double revenue;
};
// 错误: explicit 只能在类内部的构造函数声明上
explicit Sales_item::Sales_item(istream &is)
{
/* ... */
}

/* ... */
string null_book = "9-999-9999-9";
Sales_item item_a = Sales_item("1-111-1111-1");

// 以下会隐式调用构造函数,生成一个 Sales_item 对象,来进行比较
// 但这种隐式转换,未必是我们真正想要的。
// 为阻止这种隐式转换,可以在构造函数前,使用 explicit 关键字
item_a.same_isbn(null_book);

// 建议使用下面的方式,避免错误
item_a.same_isbn(Sales_item(null_book));


[cpp]
view plaincopyprint?

// 没有定义构造函数、并且,全体数据成员都是 public 的类,

// 可以采用,与数组元素相同的方式,来初始化成员
// 但,还是推荐,使用构造函数

struct Data
{
int ival;
char *ptr;
};
Data val1 = {0, 0};

// 没有定义构造函数、并且,全体数据成员都是 public 的类,
// 可以采用,与数组元素相同的方式,来初始化成员
// 但,还是推荐,使用构造函数
struct Data
{
int ival;
char *ptr;
};
Data val1 = {0, 0};


友元,允许一个类,将自己的,非公有成员的访问,授权给,指定的类或者函数。

它只能出现在类定义的内部。通常,将所有的友元声明,成组地放到类定义的开始或者结尾。

[cpp]
view plaincopyprint?

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

private:
int height;
int width;

// 友元不是 Screen的成员,

// 它可以出现在 Screen 类定义体中的,任何地方。

// 并且,不受访问控制(private、public)的影响

friend class Window_Mgr;

// 将,其他类的成员函数,设置为友元
friend Window_Mgr& Window_Mgr::relocate(Screen::index, Screen::index, Screen&);

};
class Window_Mgr

{
public:
Window_Mgr& relocate(Screen::index r, Screen::index c, Screen &s)

{
s.height += r;
s.width += c;
return *this;

}
private:

};

class Screen
{
public:
typedef string::size_type index;
private:
int height;
int width;

// 友元不是 Screen的成员,
// 它可以出现在 Screen 类定义体中的,任何地方。
// 并且,不受访问控制(private、public)的影响
friend class Window_Mgr;

// 将,其他类的成员函数,设置为友元
friend Window_Mgr& Window_Mgr::relocate(Screen::index, Screen::index, Screen&);
};
class Window_Mgr
{
public:
Window_Mgr& relocate(Screen::index r, Screen::index c, Screen &s)
{
s.height += r;
s.width += c;
return *this;
}
private:

};


要将类的成员函数,设为友元,则这个类必须先定义

要将类 或者 非成员函数 设为友元,则,不需要预先声明。

(P398,例子,貌似有误)

全局对象,会破坏封装性,而,类中定义的 静态成员,则能保持很好的封装性。

static 数据成员,与类相关联,而不是与类的对象关联。

static 成员函数,没有 this 形参。

[cpp]
view plaincopyprint?

class Account
{
public:
void applyint(){ amount += amount * interestRate; }

static double rate() {
return interestRate; }
static void rate(double);

private:
string owner;
double amount;
static double interestRate;

static double initRate();

// 例外,const 类型的静态数据成员,可以在类定义体中初始化

// 但是,即使如此,也必须在外部,进行定义

static const
int period = 30;
};
// 外部定义,但此时,无须提供初始化式
const int Account::period;

// 内部已经声明为 static 了

// 外部定义的时候,不需要再指定 static
// static 不能声明为 const、也不能声明为 虚函数

// 声明为 const 是承诺不修改该函数所属的对象,

// 然而, static 函数,不属于任何对象,它只与类关联

void Account::rate(double newRate)

{
interestRate = newRate;
}

// static 数据成员,必须在类定义体的外部定义(刚好一次)

// 一旦成员名出现,static 成员的定义,就在类作用域中了

// 因此,可以直接使用 私有成员函数 initRate

double Account::interestRate = initRate();

Account ac1;
Account *ac2 = &ac1;
double rate;
rate = ac1.rate();
rate = ac2->rate();
rate = Account::rate();

class Account
{
public:
void applyint(){ amount += amount * interestRate; }
static double rate() { return interestRate; }
static void rate(double);

private:
string owner;
double amount;
static double interestRate;
static double initRate();

// 例外,const 类型的静态数据成员,可以在类定义体中初始化
// 但是,即使如此,也必须在外部,进行定义
static const int period = 30;
};
// 外部定义,但此时,无须提供初始化式
const int Account::period;

// 内部已经声明为 static 了
// 外部定义的时候,不需要再指定 static
// static 不能声明为 const、也不能声明为 虚函数
// 声明为 const 是承诺不修改该函数所属的对象,
// 然而, static 函数,不属于任何对象,它只与类关联
void Account::rate(double newRate)
{
interestRate = newRate;
}

// static 数据成员,必须在类定义体的外部定义(刚好一次)
// 一旦成员名出现,static 成员的定义,就在类作用域中了
// 因此,可以直接使用 私有成员函数 initRate
double Account::interestRate = initRate();
Account ac1;
Account *ac2 = &ac1;
double rate;
rate = ac1.rate();
rate = ac2->rate();
rate = Account::rate();


[cpp]
view plaincopyprint?

class Bar
{
public:
private:
// static 数据成员的类型,可以是该成员所属的类类型。

static Bar mem1;
Bar *mem2;

// 错误
Bar mem3;
};
class Screen
{
public:
Screen& clear(char = bkground);

private:
// static 数据成员,可以作为默认实参。

static const
char bkground = '#';

};
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: