Jeff学C++头大第三天:类中需要注意的一些常用成员变量及函数(单例模式的实现)!

一、this指针:

指向访问成员函数对象的指针,默认是隐藏的,但也可以显示使用。
对象调用成员函数时会自动计算它的内存地址传递给成员函数中的this,而在成员函数调用其它成员函数,会把对象的地址接力传递下去。
构造函数中也有this指针,指向这个正在构造的对象,原因是构造函数执行前对象所需的内存就已经分配完毕,执行构造函数的目的是为了申请其它资源、做一些准备工作,对指针成员分配内存。

思考题:

 类的成员变量存储在每个类对象中(每个对象一份),成员函数存储在代码段中(所有的对象共享一份),那么成员函数是如何区分调用它的是哪个对象?
答:与C语言的解决方案一样,把对象的地址传递给成员函数,这样成员函数就知道是哪个对象在调用它,与C语言不同的是该操作是隐藏,编译器帮我们自动完成的,也就是类的成员函数都隐藏着一个参数,这个参数就是this指针。
this指针的用法:
    1、函数参数与成员变量重名,参数会屏蔽成员变量,可以通过this指针访问成员变量。
    2、如果成员函数需要返回当前对象的地址或引用,可以使用this指针完成。
    3、可以把this指针传递其它类对象,这样可以实现对象间的交互。

二、常函数

如果对象被const修饰,那么它就不能调用普通的成员函数,因此普通成员函数的this指针没有被const修饰,而const对象在调用成员函数传递的对象指针带const属性,因此不兼容。
在类的成员函数末尾用const修饰一下,就表示用const修饰该成员函数的this指针,这种函数叫常函数,cosnt对象只能调用常函数,常函数也只能调用函数。
如果一个成员函数可能const对象和非常对象调用,则可以重载,实现两个版本,const指针和非const指针可以影响函数的重载。
如果在常函数中要修改成员变量值,可以使用mutable修饰成员变量即可。

三、拷贝构造

拷贝构造也是一种构造函数,只是参数一个旧的对象,当使用旧对象给新创建的对象初始化时将调用拷贝构造。
    类名(const 类& that)
    {

    }
默认情况下编译器会自动生成一个拷贝构造函数,该函数负责把旧对象中的数据拷贝给新的对象。

深拷贝与浅拷贝:

    如果类的成员中有指针,在拷贝时只拷贝指针变量的值,这种叫浅拷贝,深拷贝是拷贝指所指向的数据。
    注意:默认的拷贝构造只能完成浅拷贝。

什么情况要重写拷贝构造:

    当类中的成员有指针时,想完成深拷贝的效果,就需要重写拷贝构造。

什么情况下会调用拷贝构造:

    1、使用旧对象给新对象初始化时
        Test t1 = t;
    2、使用对象作为函数的参数或返回值时。

四、赋值运行符

使用旧对象给其它对象赋值时,调用赋值运行符,它的任务就是把对象a中的数据拷贝给对象b,默认情况下也是浅拷贝。
void operator=(const 类& that)
{

}
当你需要重写拷贝构造时,也就需要重写赋值运算符。

常用考笔试题:实现string类的构造、拷贝构造、赋值运算符、析构函数。

    class String
    {
        char* str;
    public:
        String(const char* str="");
        ~String(void);
        String(const String& that);
        void operator=(const String& that);
    };        

五、关于拷贝构造和赋值函数的建议

1、拷贝构造和赋值函数不光会赋值本类的数据,也会调用父类和成员类的拷贝构造和赋值函数,而不是单纯的内存拷贝,因此尽量少使用指针成员。
2、函数的参数中尽量指针和引用,减少调用拷贝构造的次数,这样也可以提高传递的效率。
3、如果由于特殊原因无法实现拷贝构造和赋值函数,可以把实现个空的然后私有化,防止误用。
4、一旦实现了拷贝构造也要实现赋值函数,反之亦然。

六、静态成员

类的成员变量可以被static修饰,存储位置由原来的栈或堆变成data或bss,整个程序中只存在一份,被所有的对象共享(静态成员属于类,而不是某个对象)。

静态成员变量在类中声明,但必须在类外定义、初始化,与其它在类外的成员函数一样,需要加 类名:: 表示它属于哪个类,但不需要再加static。

静态成员变量虽然在类定义,但它依然受访问控制符的限制,私有成员和保护成员只能在类内访问。

静态成员变量不需要对象就可以访问,类名::静态成员变量名,public静态成员变量可以当全局变量使用。

静态成员函数也可以被static修饰,这种成员参数中就没有隐藏this指针,因此静态成员函数不需要对象就可以访问,类名::静态成员函数名,也就导致静态成员函数中不访问成员变量,也不能调用其它成员函数。

普通成员函数中可以直接访问类的静态成员变量和静态成员函数。

静态成员的作用:

    静态成员变量可以当作类范围内的"全局变量使用"。
    而静态成员函数可以作为其它函数的回调函数,或者当作类的接口,实现对类的管理。

常见的面试:C语言中的static与C++的static有什么区别?

    在C语言static具有限制作用域、改变存储位置、延长生命周期的功能。
    在C++中static又增加了新功能,可以修饰类的成员变量和成员函数。

静态成员变量:

        存储位置由原来的栈或堆变成data或bss,整个程序中只存在一份,被所有的对象共享。
        在类里面声明,在类外定义,访问时不需要对象,依然受访问控制限定符控制,只有public可以在类外访问被当作全局变量使用。
    静态成员函数:
        没有隐藏的this指针,不需要对象就可以调用,不能在函数访问成员变量和成员函数,但可以被其它成员函数调用。
        可以让类的成员函数当作回调函数,可以当作类的管理接口。

七、单例模式

只能创建出一个对象的类叫单例模式。
单例模式的应用场景:
    1、Windows系统的任务管理器。
    2、Linux\UNIX系统的日志管理系统。
    3、网站的访问计数器。
    4、服务器的连接池、线程池、数据池等。
创建单一对象的方法:
    1、定义全局的,但不受控制,且有再次创建的风险。
    2、专门实现一个类,把类的构造函数调用为私有,然后借助静态成员函数提供一个获取唯一对象的接口。
C++实现单例的思路:
    1、禁止类外创建类对象:把构造和拷贝构造设置为私有的。
    2、类自己维护一个对象:使用静态指针或静态对象。
    3、提供一个获取实例的方法:使用静态成员函数获取静态对象。

懒汉模式:

    用静态成员指针来指向唯一的单例对象,只有真正调用单例接口时才创建对象。
    优点:什么时候用什么时候创建,节约内存、资源。
    缺点:只有在调用获取接口时才创建对象,当多个线程同时调用该接口时,可能会创建出多个对象,存在线程不安全问题。
#include <iostream>
using namespace std;

class Single
{
	static Single* single;
	Single(void) {}
	Single(const Single& that) {}
public:
	static Single* get_single(void)
	{
		if(NULL == single)
		{
			single = new Single;
		}
		return single;
	}
	void show(void)
	{
		cout << single << endl;
	}
};
Single* Single::single = NULL;
void func(Single& t)
{
	cout << &t << endl;
}


int main(int argc,const char* argv[])
{
	Single* s = Single::get_single();
	s->show();
	func(*s);
}
##    

饿汉模式:
将单例对象设置为类的静态成员变量,在main函数开始运行前,实例对象就已经创建完成。
优点:获取单例对象时,线程安全。
缺点:无论是否使用,单例对象都已经创建完成,浪费内存、资源。

#include <iostream>
using namespace std;

class Single
{
	static Single single;
	Single(void)
	{
		cout << this << endl;
		cout << "我是单例构造函数" << endl;
	}
	Single(const Single& that) {}
public:
	static Single& get_single(void)
	{
		return single;
	}
};
Single Single::single;

int main(int argc,const char* argv[])
{
	cout << "hehe" << endl;
	Single& s = Single::get_single();
	cout << &s << endl;
	Single& s1 = Single::get_single();
	cout << &s1 << endl;
}


  • 2
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 1
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值