引言
这将是类和对象的最后一篇文章,相信经 过最后一篇文章的学习,一定能够加深你对类和对象的理解
1.再探构造函数
- 1.1初始化列表
在构造函数的函数名后接一个引号“ : ”,然后写需要初始化的成员对象,在成员对象后接括号,括号内是对应成员初始化的值,每个成员的初始化之间用逗号“ , ”相隔,下面将给出一个例子
class A
{
public:
A(int a, int b) : _a(a),
_b(b)
{
}
private:
int _a;
int _b;
};
- 1.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;
}
要注意到的是这里的{}初始化是利用了普通隐式类型转换,而b1 = a1用到的则是类类型的转换,这里给出程序运行的结果,是可以看到a1和b1都是成功初始化了的

3.static成员
- 3.1 特点
1.静态成员必须在类外初始化
2.static成员为所有类对象共享,不单属于某一个类,放在静态区
3.静态函数无this指针,不能够访问非静态的对象
- 3.2 例子
这里给出static成员的使用样例
class C
{
public:
C(int b): _b(b)
{}
void Aadd()
{
_a++;
}
void APrint()
{
cout << "_a = " << _a << " ";
cout << "_b = " << _b << endl;
}
static void APrint2()
{
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;
}
首先我们注意到APrint2是静态函数,是无法直接调用_b这个对象的,这里会给出报错:

再看运行结果,利用a1对静态_a对象++,a2中的_a也会改变,因此运行结果如下:

4.友元
- 4.1 定义和分类
为了突破访问限定符,分为友元函数和友元类,基本格式为:friend class A / void A()
- 4.2 特点
1.可以访问友元类的私有和保护成员
2.可以在类的任何位置声明,仅仅只是一个声明
3.一个函数可以成为多个类的友元,类也是如此
4.对于友元类函数,将B放在A中作为友元类,那B中就可以访问A的私有和保护成员,这里给出最经典的例子,关于日期类<<和>>的重载:


5.友元类的关系是单向的,也不能够传递,这里给出一个例子:
class D
{
friend class E;
private:
int _d;
};
class E
{
friend class F;
private:
int _e;
};
class F
{
public:
void PrintD(D d, E e)
{
cout << d._d << endl;
}
private:
int _f;
};
这里演示的是友元是不可以传递的,由代码可知,F是E的友元类,E是D的友元类,但是F不是D的友元类,是无法调用到D的私有成员的,如图所示:

class E
{
private:
int _e;
};
class F
{
friend class E;
public:
void PrintD(E e)
{
cout << e._e << endl;
}
private:
int _f;
};
这里演示的是友元是单向的,E是F的友元类,但是F是无法调用到E的私有成员的,如图所示:

5.内部类
- 5.1 定义
一个类定义在另一个类的内部,这个类是一个独立的类,仅仅只是受到了类域的限制
- 5.2 特点
1.默认内部类是外部类的友元
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;
};

6.匿名对象
特点是一次性使用,经常用在传参,调用函数中,匿名对象的声明周期只有这一行,下面给出使用的例子:
class L
{
public:
L(int l): _l(l)
{}
int Get()
{
return _l;
}
private:
int _l;
};
int main()
{
cout << L(3).Get() << endl;
return 0;
}
运行结果如下:

7.对象拷贝的编译器优化
- 7.1 定义
C++标准允许编译器在某些情况下省略对象的拷贝/移动操作,即使拷贝/移动构造函数有副作用。这是C++中最重要的拷贝优化机制。
- 7.2 特点
1.可能只产生临时变量,不产生拷贝对象
2.每个编译器的优化不同
- 7.3
因为这部分较为复杂,在此不过多讲解,想详细了解的可以自己去查询资料
总结
至此,类和对象的内容就这样结束了,其实这篇文章我已经写了两遍了,因为虚拟机更新忘记备份了,因此大家写博客的时候一定要勤备份啊!

评论(0)
暂无评论