C++类和对象(三) 缺省值 | static成员 | 内部类

前言:

        这是关于类和对象的最后一篇文章,当然还是基础篇的最后一篇,因为类的三大特性继承,封装和多态都还没有讲,少年,慢慢来。

缺省值:

        之前讲过,在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()

        注:虽然静态成员与类的实例不关联,但它们仍然属于类的一部分,并类的访问访问限定符(publicprotectedprivate)的影响。

        这里用一个面试题,引入关于静态成员变量的使用:实现一个类,计算程序中创建出了多少个对象:

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类型的对象。

总结: 

        嘻嘻,没总结,赶紧去完成日期类!

  • 32
    点赞
  • 21
    收藏
    觉得还不错? 一键收藏
  • 1
    评论
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值