1.引言
这将是类和对象的最后一篇文章,相信经过最后一篇文章的学习,一定能够加深你对类和对象的理解
2.再探构造函数
- 2.1初始化列表
在构造函数的函数名后接一个引号“ : ”,然后写需要初始化的成员对象,在成员对象后接括号,括号内是对应成员初始化的值,每个成员的初始化之间用逗号“ , ”相隔,下面将给出一个例子
class A
{
public:
A(int a, int b) : _a(a),
_b(b)
{
}
private:
int _a;
int _b;
};
- 2.2特点
1.每个成员只能初始化一次
2.每个成员对象都要走初始化列表
3.const类型,引用,和没有默认构造的自定义类型对象只能够在初始化列表中定义,否则会报错
4.尽量使用初始化列表初始化
5.初始化列表初始化的顺序是按照声明的顺序初始化的,而不是定义,给出一个例子
class A
{
public:
A(int a, int b) : _b(b),
_a(a)
{
}
private:
int _a;
int _b;
};
这里初始化的顺序是a->b,而不是b->a
6.构造函数中可以给缺省值,成员对象也可以给缺省值
2.隐式类型转换
1.C++支持内置类型隐式类型转换为类类型对象,需要有相关内置类型为参数的构造函数,多参数的要用{}
2.如果在构造函数前加explict,就可以防止隐式类型转换
3.类类型之间也支持隐式类型转换,但需要相对应的构造函数
这里给出隐式类型转化的例子
class A
{
public:
A(int a, int b) : _a(a),
_b(b)
{
}
void Print()
{
cout << _a << " " << _b << endl;
}
int Get() const
{
return _a + _b;
}
private:
int _a;
int _b;
};
class B
{
public:
B(const A& a) : _a(a.Get())
{
}
void Print()
{
cout << _a << endl;
}
private:
int _a;
};
int main()
{
//类类型隐式类型转换
A a1 = { 1, 2 };
a1.Print();
B b1 = a1;
b1.Print();
return 0;
}
运行结果如下:

3.static成员
- 3.1 特点
1.静态成员必须在类外初始化
2.静态成员为所有类对象共享,不专门属于任何一个类对象,放在静态区内
3.静态成员函数无this指针,因此不能访问非静态的对象
- 3.2 例子
class C
{
public:
C(int b): _b(b)
{}
void Aadd()
{
_a++;
}
void APrint()
{
cout << "_a = " << _a << " ";
cout << "_b = " << _b << endl;
}
private:
static int _a;
int _b = 3;
};
//在类外进行初始化
int C::_a = 0;
int main()
{
C a1(2);
C a2(3);
a1.APrint();
a2.APrint();
//利用a1对静态_a对象++,a2中的_a也会改变
a1.Aadd();
a2.APrint();
return 0;
}
这里给出运行结果:

4.友元
- 4.1 用法
是一种访问限定符,分为友元函数和友元类,具体用法是将类声明或者函数声明前加“friend”,然后放入需要友元的类中,这样可以访问到成功友元的类中的成员,这里给出一个最经典的例子,也就是<<的重载:


可以看到,这里通过友元的方式,就能直接访问到类中private里的成员对象
- 4.2 特点
1.可以访问类的私有和保护对象
2.可以在类中的任何位置声明(仅仅只是声明)
3.一个函数可以成为多个类的友元
4.友元类的关系是单向的,不能够传递,尤其是对于友元类来说,这里给出一个例子:
class D
{
friend class E;
private:
int _d;
};
class E
{
friend class F;
private:
int _e;
};
class F
{
public:
void PrintD(D d)
{
cout << d._d << endl;
}
private:
int _f;
};
注意,这里是不能访问到_d的,放在编译器中则可以看到明显的报错:

5.内部类
- 5.1 定义
一个类定义在另一个类的内部,是一个独立的类,仅仅只是受到了类域限制
- 5.2 特点
默认内部类是外部类的友元,也就是内部类可以访问外部类的成员,但是同友元类相同,外部类是无法访问内部类的私有和保护成员的,这里给出例子
class H
{
class h
{
public:
void Print(H a)
{
cout << a._H;
}
private:
int _h = 2;
};
public:
void Print(h a)
{
cout << a._h;
}
private:
int _H = 1;
};
当我们把这段代码放进编译器中时,会发现h类中的Print函数是可以正常访问的,但是H类中的函数就不行:

6.匿名对象
- 6.1 用法
直接写类名+()进行初始化,如下:
class L
{
public:
L(int l): _l(l)
{}
int Get()
{
return _l;
}
private:
int _l;
};
int main()
{
cout << L(3).Get() << endl;
return 0;
}
- 6.2 意义(特点)
匿名对象是一次性的,生命周期只存在于这一行,通常被使用在调函数和传参中
7.对象拷贝时的编译器优化
- 7.1 定义
编译器在不影响其正确性的情况下,会减少一些传参和返回值的拷贝,能合并的都会尽量合并,以提高编译的效率,特别是在release版本中
- 7.2 特点
1.对于传参,可能只产生临时变量,而不进行拷贝
2.不同的编译器的优化是不同的
- 7.3 特记
因为这个如果要仔细讲的话篇幅很长,所以可以自己下去了解,以后有时间我也会单独写一篇关于编译器优化的文章
8.总结
类和对象篇终于结束,还是用了将近一个周的时间才完成,后续也将会继续整理关于c++学习的文章

评论(0)
暂无评论