前言:
这是关于类和对象的最后一篇文章,当然还是基础篇的最后一篇,因为类的三大特性继承,封装和多态都还没有讲,少年,慢慢来。
缺省值:
之前讲过,在C++11的新标准中,支持为类中的成员变量提供缺省值。在类和对象中,提供的缺省值是提供给初始化列表使用的。由于支持隐式类型转换构造等原因,提供的缺省值可以非常灵活,见代码:
class A
{
public:
A(int a1)
:_a1(a1)
{
cout << "A(int a1)" << endl;
}
A(int a1, int a2)
:_a1(a1)
, _a2(a2)
{
cout << "A(int a1, int a2)" << endl;
}
A(const A& aa)
:_a1(aa._a1)
, _a2(aa._a2)
{
cout << "A(const A& aa)" << endl;
}
private:
int _a1;
int _a2;
};
class B
{
public:
private:
int _b1 = 1;// 缺省值可以给整型变量
int* ptr = (int*)malloc(40);// 可以开空间给指针
A _aa1 = 1;// 可以给对象类型(A _aa1(1);这样构造是错误的)
A _aa2 = { 1,2 };// 多参数构造
A _aa3 = _aa2;// 拷贝构造,缺省参数甚至可以是一个对象
};
int main()
{
B bb1;
return 0;
}
这些缺省参数,最终都会提供给初始化列表。也就是说,你没有写初始化列表,这些值他就会默认提供。
如果显示提供了初始化列表,运行时,这些被提供的缺省参数就会被忽略(简单说就是:如果既提供了初始化列表,也有缺省值,编译器默认使用初始化列表提供的值)。
static成员:
不知道大家学过Java没有,我们再C语言中也知道,static是静态变量它的内存会开辟在静态区,生命周期会延长。
静态成员变量:
声明为static的类成员称为类的静态成员,用static修饰的成员变量,称之为静态成员变量;用static修饰的成员函数,称之为静态成员函数。静态成员变量一定要在类外进行初始化。
静态数据成员在类的所有对象之间共享。这意味着无论创建了多少个对象,都只有一个静态数据成员的副本,且此副本存放在静态区(这里和Java是一样的)。静态数据成员必须在类定义外部进行初始化,且定义时不添加static关键字,类中只是声明。如:
class MyClass {
public:
static int count; // 声明静态数据成员
};
int MyClass::count = 0; // 在类定义外部初始化静态数据成员
静态函数:
静态成员函数是类的一个成员函数,它可以在没有类的实例的情况下调用。静态成员函数只能访问静态成员(包括静态成员变量和其他静态成员函数)。它们不能访问类的非静态成员(这里与Java是一样的),因为非静态成员需要类的实例才能存在,本质上说,静态成员函数没有隐藏的this指针,本身就是无法访问任何非静态成员的。如:
class MyClass {
public:
static int count;
static void GetCount() {
count++; // 可以访问静态数据成员
}
void doSomething() {
// 这里不能访问静态成员count,除非使用 MyClass::count
}
};
访问静态成员或函数:
你可以使用类名和作用域解析运算符( :: )来访问静态成员,无论是否创建了类的实例。例如,MyClass::count
和 MyClass::GetCount()
。
注:虽然静态成员与类的实例不关联,但它们仍然属于类的一部分,并受类的访问访问限定符(如public、protected
或private
)的影响。
这里用一个面试题,引入关于静态成员变量的使用:实现一个类,计算程序中创建出了多少个对象:
class A
{
public:
A() { ++_scount; }
A(const A& t) { ++_scount; }
~A() { --_scount; }
static int GetACount() { return _scount; }
private:
static int _scount;
};
int A::_scount = 0;
void TestA()
{
cout << A::GetACount() << endl;
A a1, a2;
A a3(a1);
cout << A::GetACount() << endl;
}
·因为在调用TestA时,创建了3个对象,在调用完以后才会析构。
内部类:
这个和Java不一样,一般很少使用,它仅仅是对生命作用域进行了限制,相对于任何类都是平行的关系。
概念:如果一个类定义在另一个类的内部,这个内部类就叫做内部类。内部类是一个独立的类,它不属于外部类,更不能通过外部类的对象去访问内部类的非共有成员。外部类对内部类没有任何优越的访问权限。
注:内部类就是外部类的友元类,参见友元类的定义,内部类可以通过外部类的对象参数来访问外部类中的所有成员。但是外部类不是内部类的友元。
class A
{
private:
static int k;
int h;
public:
class B // B天生就是A的友元,可以直接访问A
{
public:
void foo(const A& a)
{
cout << k << endl;//OK
cout << a.h << endl;//OK
}
};
};
int A::k = 1;
int main()
{
A::B b;
b.foo(A());
return 0;
}
上述代码中,演示了这一系列特性,总的来说,B定义在A里面只是受A的类域限制,其他除了访问限定符影响类成员的访问之外,就和两个独立定义的类没什么区别了。当class B定义在private里时,就无法通过A::B bb;创建B类型的对象。
总结:
嘻嘻,没总结,赶紧去完成日期类!