C++ Primer学习 《Classes》

本文详细介绍了C++中的类基础,包括this指针、const成员函数、类内顺序、构造函数的使用、类的控制和封装、类的其他特性、类作用域规则以及静态类成员。探讨了构造函数的重要性,如构造初始表、委托构造函数,并强调了静态成员的定义和使用。此外,还讨论了友元函数和友元类,以及如何在类的内部和外部声明和使用它们。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

Classes(基础)

1. 类的基础介绍

定义在class内部的函数默认是inline的。

1.1 this指针介绍

当我们通过object调用类成员函数时,有一个指向这个object的指针被传递给这个函数,这个指针叫做this指针。

例如当我们调用:

total.price();
实际上相当于:

price(&total);//pseudo-code
因为this永远指向当前object,因此this是一个const指针,我们不能改变this的地址。但是this指向的object当然是可以改变的。因此this是一个top-level const pointer,不一定是low-level const pointer。

1.2 const 成员函数介绍

类成员函数有时被声明为const类型,这意味着该类成员函数不会修改this指向的object。而没有被声明为const类型的类成员函数,则自然可以修改这个object。因此,如果object是const,那么我们就不能调用nonconst类成员函数。

class testConst
{
public:
	int constMemberFunction(){ return 0; }
        int constMemberFunction2() const { return 0; }//const 类成员函数
};

testConst a;
a.constMemberFunction();//ok
const testConst b;
b.constMemberFunction();//error!
b.constMemberFunction2();//ok!

具体说来,在上面的例子中,第一个类成员函数constMemberFunction将this指针定义为int* const类型,而在第二个类成员函数constMemberFunction2中将this指针定义为const int * const类型。大家可以自行体会。

1.3 类内顺序(class scope)

在类的定义中,先出现的函数可以在函数体内调用后出现的变量。即:

class scopeTest
{
    int print(){cout << answer << endl;}//ok!尽管answer在后面定义
    int answer;
};
这是因为,C++编译器在编译类时分两步,第一步:对所有变量和类成员函数的声明进行编译;第二步:处理函数体。

Return “this” object

直接返回this指向的object,一般的写法是:

class thisTest
{...};
thisTest& thisTest::add(const thisTest&)
{
...
return *this;
}

1.4 构造函数(Constructors)

和其他函数不同的是,构造函数没有返回类型。一个类可以有多个构造函数,只要满足函数重载的规则即可。

构造函数不能定义为const函数,这很容易理解。即使我们要创建一个const object,在创建的过程中我们无疑需要对这个object进行一些赋值。

默认构造函数(default constructor)

默认构造函数没有任何参数。默认构造函数可以显式声明,只要没有参数就属于默认构造函数。

编译器自动生成的构造函数通常被称作:synthesized default constructor。在这个函数中,编译器遵循如下法则初始化类内各个成员:
1.如果有in-class initializer(在类内直接赋初值),则使用这个值。

2.否则,对成员进行default initialize。(int等被赋为0等)

有时不能依赖synthesized default constructor

1.只有当类没有定义任何构造函数时,编译器才会为我们定义一个synthesized default constructor

2.当成员是built-in type 或 compound type时(arrays , pointers等),default initialize会产生undefined value,这是我们绝对不希望的。

3.有时,编译器无法完成synthesized default constructor的工作。比如,一个类内部有一个成员是另一个类,而那个类没有构造函数,等等情况。

=default 

有时,我们在定义各个类内成员时,已经写好了in-class initializer,那么可能会觉得再写一个构造函数比较麻烦,这时可以用=default 语句。

class defaultConstructorClass
{
...
defaultConstructorClass() = default;
};
一般来说,只有当我们同时需要定义其他的构造函数时,才会这么写,否则,直接不定义不就好了嘛。

constructor initializer list

在定义构造函数时,有一个比较与众不同的东西叫做constructor initializer list。

形式如下:

className(string &s) : bookNo(s){}
className(string &s,unsigned n,double p) : bookNo(s),units_sold(n),revenue(p*n)  {}

及时我们需要将构造函数定义在类外,这种constructor initializer list也依然是可以使用的。

一般来说,最好能使用in-class initializer,但如果编译器不支持,那我们必须这样声明。


2. 控制Class以及包裹Class

2.1 class和struct关键词

struct和class几乎是可以互换的,只是一种风格的不同。

唯一的区别是,默认情况下(没有声明public,private等),struct下的成员是public的,而class下的成员是private的。

至于编程风格上,如果我们的类中所有成员都是public的,那么我们用struct。如果有private成员,那我们用class。

2.2 友元(Friends)

将其他类或函数声明为友元(friends)后,该类或函数就能调用本类中的非public成员。

例如:

class friendClass
{
friend friendClass add(...);//一个类外函数
friend anotherClass;//另一个类
};
friends函数不受private或public影响,但是作为好的习惯,我们应该将他们放在一起,放在class中的最开始,或者最后。

另外,class内的友元函数的声明,只是表明一个权限(access),而不是一般意义上的声明。如果在类的外部我们需要使用这个友元函数,那么我们还需要再次声明这个函数!

一般来说,我们会将这些友元函数的声明和这个类放在同一个头文件中。

而如果是将一个类声明为友元,则可以在两个头文件中都包含一下另一个类的简单声明。(这个是我自己认为的)


3.类的其他特性

3.1 类成员

Type Member

在类的定义中,我们还可以定义type。type也会受到public和private的限制。

class testConst
{
public:
	using publicint = int;
private:
	using privateint = int;
};

testConst::publicint a = 0;//ok!
testConst::privateint b = 0;//error!

值得注意的是,和其他类成员不同,type member必须先定义,再使用!因此,一般讲typedef / type alias声明在类的最前面。

Inline Members

前面提到过,在类的内部完全定义好的函数默认是inline的。同时我们也可以显式要求某个函数是inline的。

我们可以在类的内部声明inline标示符,可以在类外部定义时声明inline标示符,也可以在两个地方都声明,效果是一样的。但是,C++ Primer建议,只在类的外部声明in

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值