C++深入理解系列-类对象的限制

前沿

最近每天睡前都会看efficient c++ ,每天一个条款,看了几天,发现有好多有用的c++编程技巧,想了下,为了巩固一下自己所看,准备定时在这边总结分享一下,一起交流学习。

一.单例模式的另外一种实现

目前现有限制对象个数的机制就是常用的单例模式:

静态成员:

类中的成员加入static修饰符,即是静态成员,可以使用类名+静态成员名访问此静态成员,外部可以直接访问类中的静态成员。

1.因为==静态成员存在于内存==,生命周期是随着类的加载而分配内存,随着类的消失而释放,与类对象无直接关系。

2非静态成员随着对象的生成实例化才会分配内存,在时间顺序上静态成员比非静态成员早,所以理论上静态成员不能访问非静态成员,否则会出现访问不到的问题。
3.静态成员,是所有类对象共享的,也就是说,假如有3个类对象,类中有一个静态成员,那么任何一个对象修改静态成员,其他类对象中去读取这个静态成员的值也都会随之改变,相当于static 是这些对象的全局变量。


非静态成员:

所有没有加static的成员都是非静态成员,当类被实例化后,可以通过实例化的类名进行访问,非静态成员的生存期决定于该类的生存期,而静态成员则不存在生存期的概念,因为静态成员始终驻留在内存中。

单例模式:

简单的单例模式

class SingleTest
{
public:
    //类对象声明成静态,就是为了让运行时只有一个类对象
    static  SingleTest *sInstance ; 
    static SingleTest *getInstance() {
        if(sInstance == NULL)
            sInstance = new SingleTest();

        return sInstance;
    }
    void helloSingle(){
        std::cout<<"hello single!";
    }
private:
    SingleTest()
    {
        cout << "This is  a SingleTest class!!" << endl;
    }

    virtual ~SingleTest()
    {
        if(sInstance != NULL)
            delete sInstance;
    }

};
//静态成员必须在类外初始化定义,这也印证了它是全局共享的理论
SingleTest* SingleTest::sInstance = NULL;

int main(){
    //类对象初始化调用静态成员函数的方式
    SingleTest *instance = SingleTest::getInstance();
    instance->helloSingle();
    return 0;
}

友元函数的机制

以上是单例模式的理论和使用方式,接下来有一种方式可以替代它,而且初始化对象时不需要加上类域符号,原理就是利用类友元函数可以访问类中私有成员的这个特点。

class ImageVector{

public:

    void setImageUrl(std::string& str);
    virtual ~ImageVector();
    //定义友元函数,返回类对象的引用
    friend ImageVector& getImage();
private:
    ImageVector();
    ImageVector(const ImageVector& other){}


};
ImageVector& getImage();//类函数声明

//友元函数的实现
ImageVector &getImage() {
    static ImageVector p;//声明一个静态对象

    return p;
}

void ImageVector::setImageUrl(std::string &str) {
    std::cout<<"std = "<<str<<std::endl;

使用方式:

int main(){
    std::string url = "http://www.image.com";
    getImage().setImageUrl(url);
    //调用的代码很清晰
    return 0;
}

这里讨论下代码的原理:

与单例模式的不同点:
1.类对象的生命周期,单例模式是跟随着类的生命周期,即使你在主函数中没有调用这个类,这个静态类对象也存在类存中。而下面这种友元方式,类静态对象存在于函数中,生命周期的开始是在这个友元函数被调用的那时候算起,直到程序结束。

函数中声明的静态对象也是存在于全局内存中的,不在栈内存上,所以不会随着函数周期的结束而释放,同样下一次函数再次被调用的时候,并不会再次声明对象。

优势在于可以在使用的时候去分配对象类存,代码清晰,同样达到一个效果,函数运行时,只有一个类对象存在。

二.限制类对象声明次数

上面的无论是单例模式还是友元机制的方式都只能允许运行时只有一个类对象存在,现在想要达到的目的是,运行时允许多个对象的生成,但对对象的个数有限制。

对上面的类稍做修改:

class ImageVector{

public:
    //内部异常类
    class ImageEception{
    public:
        ImageEception(){
            std::cout<<"You define too many objects!"<<std::endl;
        }
    };
    //这个时候类构造函数变成public,外部可访问
    ImageVector();
    virtual ~ImageVector();
    void setImageUrl(std::string& str);
    void showUrl();


    //定义对象计数,要为静态成员
    static int number;

    friend void test(){std::cout<<"111"<<std::endl;}
    friend ImageVector& getImage();
private:

    ImageVector(const ImageVector& other){}
    std::string m_str;

};


int ImageVector::number = 0;

ImageVector::ImageVector() {
    m_str = "default";
    number++;
    if(number > 2)
        throw ImageEception();

}

ImageVector::~ImageVector() {
    number--;
}

以上代码就可以实现限制对象个数为2个,超过两个类会抛出异常。

  • 0
    点赞
  • 4
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值