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

总结: 

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

相关推荐

最近更新

  1. TCP协议是安全的吗?

    2024-05-13 03:08:05       16 阅读
  2. 阿里云服务器执行yum,一直下载docker-ce-stable失败

    2024-05-13 03:08:05       16 阅读
  3. 【Python教程】压缩PDF文件大小

    2024-05-13 03:08:05       15 阅读
  4. 通过文章id递归查询所有评论(xml)

    2024-05-13 03:08:05       18 阅读

热门阅读

  1. Python 自动化脚本系列:第3集

    2024-05-13 03:08:05       14 阅读
  2. 拼接图片路径不显示:vue

    2024-05-13 03:08:05       10 阅读
  3. 力扣 516. 最长回文子序列 python AC

    2024-05-13 03:08:05       15 阅读
  4. 【linux软件基础知识】-cdev_alloc

    2024-05-13 03:08:05       11 阅读
  5. halcon学习之形状匹配

    2024-05-13 03:08:05       6 阅读
  6. logback 日志脱敏

    2024-05-13 03:08:05       7 阅读
  7. Google Gemma 2B 微调实战(IT科技新闻标题生成)

    2024-05-13 03:08:05       12 阅读
  8. 生成ssh来连接git

    2024-05-13 03:08:05       11 阅读
  9. 旋转木马案例

    2024-05-13 03:08:05       8 阅读
  10. HTTP 结构概述

    2024-05-13 03:08:05       11 阅读
  11. Android app通过jcifs-ng实现Samba连接共享文件夹

    2024-05-13 03:08:05       10 阅读
  12. MySQL教程-输入查询

    2024-05-13 03:08:05       10 阅读