C++学习-类2
静态成员
静态数据成员
关键字static,可以实现不同对象之间的数据共享。
组成:类内声明,类外初始化。两者缺一不可
\\类内声明
static 数据类型 名;
\\类外初始化
数据类型 类名::静态数据成员名=初始值;
- 必须要类内声明内外初始化,如果内外无初始化会报错。
定义类时不会为静态数据成员分配空间,类外初始化才分配空间 - 和其他类内的数据成员一样,private只能在类内使用,public可以在内外使用
- 不属于对象属于类,但所有对象都共用。可以通过域操作符直接调用 如
类名::rate
,也可以有可以通过对象引用,如:对象名.rate
- 程序开始时产生,结束时消失
补充:静态常量成员,定义:static const 类型 数据成员名
静态常量成员后两种初始化方法,一种是类外,一种是类内。
class AA
{
private:
static const int num;
};
const int AA::num=3;
//或者
class AA
{
private:
static const int num=3;
};
而静态数据成员必须是类内声明,类外初始化。
静态成员函数
静态成员函数时为累的全体对象服务,不需要借助任何对象就可以调用,无法处理类中非静态成员变量,也不允许需用this指针。
类内定义在定义前在static,类内声明类外定义,只要在声明前加static,类外定义时不需要加static
调用方式:类名::函数名 或 对象.函数名
- 静态成员函数不能访问一帮的数据成员,而只能访问静态数据成员或其它静态成员函数。但如果传递该类的对象或对象的引用,或者在函数内创造一个该类的对象,那么可以使用该对象的所有成员,包括私有(如果不是常对象)。
#include<iostream>
using namespace std;
class AA
{
private:
int a;
public:
AA(int h=0)
{
a=h;
}
static void abc(AA &aa)
{
aa.a++;
cout<<aa.a;
}
};
int main()
{
AA aa;
AA::abc(aa);
return 0;
}
结果输出1。
友元
友元不是类的成员,当他可以访问类的任何成员包括私有成员,友元包括友元函数,友元成员函数,友元类。
friend是关键字,格式为:
friend 返回类型 函数名(形参表)
{
函数体;
}
下面依次介绍三种。
友元函数
//在类A中加入
friend void f();//把函数f作为类A的友元,可以类内定义也可以类外定义函数。如果类外定义,类外不需friend。
友元成员函数函数:
B的成员函数:int func(double);
若声明为类A的友元,在类A定义中加入:
friend int B::func(double);
友元类
//在类A中加入
friend class B;//把整个类B作为类A的友元
友元关系声明可以放在函数任意一个地方,,可以私有也可以公有,效果不会影响,不过一般放在最前面或最后面。
补充:前向引用声明,和函数的声明差不多,可以在后面定义类然后在开头加上声明。
#include <iostream>
using namespace std;
class B; //前向引用声明。
class A{
public:
void f(B &b);
private:
B *b; // 不能使用 B b
};
class B{
public:
void g(A a);
private:
A a;
};
但前向引用声明不是万能的。
在声明之前,不能声明该类的对象,也不能在内联成员函数中使用该类对象。
前向引用声明时,只能使用被声明的符号,不能涉及类的任何细节。
class Fred;
class Braney{
Fred x; // 错误:类Fred的声明尚不完善。
};
class Fred{
Braney y;
};
课堂上的笔记补充:
- 如果自己定义任意一个普通的构造函数,则系统不再提供默认构造函数,但会提供一个默认的拷贝构造函数;如果定义了一个拷贝构造函数,则系统不再提供默认构造函数和默认拷贝构造函数
- 如果函数的返回值是常量,或传递的实参是个常量,或给对象初始化的是一个常量,如
Clock(1,2,3);
(Clock是类名),则调用构造函数而不是拷贝构造函数。