C++学习16_类和对象(对象的组织、单例模式)

对象的组织

有了自定义类,或别人定义好的类之后,就可以使用其来创建对象。

其机制与使用int等创建普通变量几乎完全一致。

同样可以通过类创建const对象、指向对象的指针、对象数组,动态对象(new/delete)

const对象

类对象可以声明为const对象。

因为const对象只能被创建、撤销和只读访问,不允许被改写。

所以, 一般来说,除了构造函数和析构函数,能作用于const对象的成员函数只有const成员函数。

//举例代码:
const Point pt(1, 2);
pt.print();

指向对象的指针

指针中存储:对象所占内存空间的首地址。

//格式:
类名 *指针名 [=初始化表达式];
//初始化表达式是可选的,
//可以通过取地址(&对象名)给指针初始化,
//也可以通过申请动态内存给指针初始化,
//或者干脆不初始化(如置为nullptr),在程序中再对该指针赋值。

//举例代码:
Point pt(1, 2);
Point *p1 = nullptr;
Point *p2 = &pt;
Point *p3 = new Point(3, 4);	//构造函数初始化
Point *p4 = new Point[5];		//类数组(堆空间)

p3->print();		//指针直接通过指向访问成员函数,合法
(*p3).print();		//指针通过解引用调用成员函数,合法

对象数组

和标准类型数组相比,对象数组的使用方法并没有什么不同,都有声明、初始化和使用3个步骤。

  1. 声明:
类名 数组名[对象个数];
//自动调用默认构造函数,或所有参数都是自定义默认值的构造函数。
  1. 初始化:(也可将声明与初始化同时进行)
//完整书写数组元素个数和类构造内容
Point pts[2] = {Point(1, 2), Point(3, 4)};
//缺省数组元素个数
Point pts[] = {Point(1, 2), Point(3, 4)};
//未将数组所有元素进行初始化
Point pts[5] = {Point(1, 2), Point(3, 4)};

//或者,去掉Point的书写,则( )换成{ }
Point pts[2] = {{1, 2}, {3, 4}};
Point pts[] = {{1, 2}, {3, 4}};
Point pts[5] = {{1, 2}, {3, 4}};

堆对象

用new和delete表达式为对象分配动态存储区。

这里主要讨论如何为对象对象数组动态分配内存

//举例代码:
void test()
{
    //为对象分配动态内存
    Point *pt1 = new Point(11, 12);
    pt1->print();
    delete pt1;
    pt1 = nullptr;
    
    //为对象数组分配动态内存
    Point *pt2 = new Point[5]();//5个类对象元素
    //赋值方式:
    pt2[0] = Point(1, 2);		//第一种赋值方法
    pt2[1] = {3, 4};			//第二种赋值方法
    //打印方式:
    pt2->print();
    (pt2 + 1)->print();
    delete [] pt2;
    //使用free去进行释放,会core dumped,
    //故不能将new和free混用,应该是new和delete搭配使用
}

单例模式

设计需求

一个类只能创建一个对象。

单例模式是23种 GOF 模式中最简单的设计模式之一,属于创建型模式,它提供了一种创建对象的方式,确保只有单个对象被创建。

应用场景

全局对象,或全局唯一资源,如:日志记录器、网页库、字典库等。

实现步骤:

  1. 将构造函数和析构函数设置为私有(private),防止在类外部多次创建/撤销多个对象(栈对象可以被多次创建)。
  2. 将创建/撤销对象的自定义成员函数设置为静态(static)公有(public),创建对象的静态成员函数——返回值为类指针。方便在类外调用静态且唯一的创建/撤销对象自定义成员函数,而且可以直接用类名来调用,不用对象名调用。
  3. 设置一个接收对象空间地址的j静态(static)指针数据成员 (_pInstance),保证创建/撤销操作只对应1个对象。

举例代码

//举例代码:
class Singleton{
public:
    //自定义函数创建对象
	static Singleton * getInstance(){	//保证1个类只创建1个对象
        //如果指针为空,则代表对象尚未被创建,则要创建对象
    	if(nullptr == _pInstance){
    		_pInstance = new Singleton();
		}
        //如果指针不为空,则代表已有对象,直接返回对象指针。
        return _pInstance;
    }
    //自定义函数撤销对象
    static void destroy(){
        //如果指针不为空,则代表对象仍然存在,故执行delete语句,防止多次delete。
        //如果指针为空,则代表对象不存在了,故没有必要执行delete语句,防止多次delete。
        if(_pInstance){		
    		delete _pInstance;
            _pInstance = nullptr;
		}
    }
    
private:
    //将构造函数和析构函数设为私有,防止外部调用构造函数/析构函数从而改变临时的栈对象。
    Singleton()
    {
    	cout << "Singleton()" << endl;
    }
    ~Singleton()
    {
    	cout << "~Singleton()" << endl;
    }
    
private:
    //全局静态数据成员
    static Singleton *_pInstance;
};

//初始化静态数据成员(全局位置)
Singleton *Singleton::_pInstance = nullptr;

int main(void)
{
    /* Singleton s1; // error,此时s1是栈对象,可多次创建栈对象,不符合单例模式要求。*/
    /* Singleton *ps1 = new Singleton(); // error,此时s1是堆对象,但是指针ps1处于栈空间,也不合适。*/
    Singleton *ps1 = Singleton::getInstance();//用自定义函数创建对象。
    Singleton *ps2 = Singleton::getInstance();//实际上ps1和ps2指向同一对象。
    cout << "ps1 = " << ps1 << endl << "ps2 = " << ps2 << endl;
    
    //开始delete操作
    /* delete ps1;//error,未在main函数中进行new操作,直接在main中delete不合适; */
    /* delete ps2;//进行一个delete后,实则已经delete掉对象所在空间了,再一次delete就重复了,会core dumped。*/
    ps1 -> destroy();//正确做法:用自定义函数删除对象
    Singleton :: destroy()//正确做法:用类名直接调用静态static函数

    return 0;
}
/* delete ps2;//进行一个delete后,实则已经delete掉对象所在空间了,再一次delete就重复了,会core dumped。*/
ps1 -> destroy();//正确做法:用自定义函数删除对象
Singleton :: destroy()//正确做法:用类名直接调用静态static函数

return 0;

}


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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值