C++之对象的使用

1、static成员

2、static成员优点

2、static成员函数

静态成员函数不能访问非静态成员原因:因为没有this指针。也不可以访问非静态成员函数。

可以通过对象来访问静态成员,但是不推荐这么使用,会让人误解成这个x_是属于对象的,但是静态成员是属于类的。

3、类/对象大小计算

一个虚函数,会增加4个字节,因为增加了一个虚函数表指针。

4、四种对象的作用域与生存期

bss区,即block started by symbol,因为未初始化的数据,在可执行文件中不占用空间,因为他们的初始值都为0,既然等于0,我们只需要一个符号来表示即可,不需要再为它们分配空间。

5、static用法总结

6、static与单例模式

禁止拷贝:将拷贝构造函数和等号运算符声明为私有的,这样就不允许拷贝和赋值

#include <iostream>
using namespace std
class Singleton
{
public:
    static Singleton* GetInstance()
    {
        if(instacne_== NULL)
        {
            instacne_= new Singleton;
        }
        return instacne_
    }
    
    ~Singleton()
    {
        cout<<"Singleton"<<endl;
    }
private:
    Singleton(const Singleton& other);
    Singleton& operator=(const Singleton& other)
    Singleton()
    {
        cout << "Singleton..." << endl;
    }

    static Singleton* instacne_;
}

Singleton* Singleton::instacne_;

int main(void)
{
    //Singleton sl;
    //Singleton s2;

    Singleton* sl = Singleton::GetInstance();
    Singleton* s2 = Singleton::GetInstance();

    //Singleton s3(*s1)  // 调用拷贝构造函数

    return 0;
}

还有就是:在构造函数中,开辟的内存,在单例的这个对象生命周期结束的时候自动释放

方法一:提供一个释放内存的方法,主动调用

#include <iostream>
using namespace std
class Singleton
{
public:
    static Singleton* GetInstance()
    {
        if(instacne_== NULL)
        {
            instacne_= new Singleton;
        }
        return instacne_
    }
    
    ~Singleton()
    {
        cout<<"Singleton..."<<endl;
    }

    static void Free()
    {
        if (instance_ != NULL)
        {
            delete instance_;
        }
    }
private:
    Singleton(const Singleton& other);
    Singleton& operator=(const Singleton& other)
    Singleton()
    {
        cout << "Singleton..." << endl;
    }

    static Singleton* instacne_;
}

Singleton* Singleton::instacne_;

int main(void)
{
    //Singleton sl;
    //Singleton s2;

    Singleton* sl = Singleton::GetInstance();
    Singleton* s2 = Singleton::GetInstance();

    //Singleton s3(*s1)  // 调用拷贝构造函数

    Singleton::Free()
    return 0;
}

但是这样缺点也很明显:如果一个程序很多地方都使用了一个单例的对象,我们要释放,要在哪里释放?这个就不好控制了。我们需要的是在这个对象的声明周期结束的时候自动释放。

方法二:提供一个内嵌的嵌套类,然后再定义一个嵌套类的对象,当该单例对象的声明周期结束的时候,这个嵌套类的对象也就释放了。

#include <iostream>
using namespace std
class Singleton
{
public:
    static Singleton* GetInstance()
    {
        if(instance_== NULL)
        {
            instance_= new Singleton;
        }
        return instance_
    }
    
    ~Singleton()
    {
        cout<<”Singleton'<<endl;
    }

    //static void Free()
    //{
    //    if (instance_ != NULL)
    //    {
    //        delete instance_;
    //    }
    //}
    
    class Garbo
    {
    public:
        ~Garbo()
        {
            if(Singleton::instance_!= NULL)
            {
                delete instance_,
            }
        }
    }

private:
    Singleton(const Singleton& other);
    Singleton& operator=(const Singleton& other)
    Singleton()
    {
        cout << "Singleton..." << endl;
    }

    static Singleton* instance_;

    static Garbo garbo_;  // 利用对象的确定性析构:因为是在栈上的内存,生命周期结束的时候会自动调用~Garbo()这个析构函数
}

Singleton* Singleton::instance_;
Singleton::Garbo Singleton::garbo_;

int main(void)
{
    //Singleton sl;
    //Singleton s2;

    Singleton* sl = Singleton::GetInstance();
    Singleton* s2 = Singleton::GetInstance();

    //Singleton s3(*s1)  // 调用拷贝构造函数

    return 0;
}

但是这样的情况下在类中又嵌套了一个类,看起来还是不美观。

方法三:auto_ptr智能指针,这个等后期再讲

方法四:这边是利用了一个static的特性,如果你第二次调用的话,那就不会再重新生成一个static对象,会用原来的。而且是一个局部静态对象,当程序结束的时候,就会调用析构函数销毁。但是这样,不是线程安全的。

#include <iostream>
using namespace std
class Singleton
{
public:
    static Singleton& GetInstance()
    {
        static Singleton instance;
        return instance;
    }
    
    ~Singleton()
    {
        cout<<"~Singleton..."<<endl;
    }


private:
    Singleton(const Singleton& other);
    Singleton& operator=(const Singleton& other)
    ~Singleton()
    {
        cout << "Singleton..." << endl;
    }

}

int main(void)
{
    Singleton& sl = Singleton::GetInstance();
    Singleton& s2 = Singleton::GetInstance();

    return 0;
}

7、const成员函数

const也可以构成重载。

#include <iostream>
using namespace std;

class Test
{
public:
    Test(int x):x_(x)
    {
        
    }

    int GetX() const
    {
        cout << "const GetX ..." << endl;
        //x_ = 100;  // 这样会报错
        return x_;
    }

    int GetX()
    {
        cout << "GetX ..." << endl;
        return x_;
    }
private:
    int x_;
}

int main(void)
{
    return 0;
}

8、const对象

因为const对象不允许修改,所以如果const对象允许调用非const成员函数,那就有被修改的风险。

#include <iostream>
using namespace std;

class Test
{
public:
    Test(int x):x_(x)
    {
        
    }

    int GetX() const
    {
        cout << "const GetX ..." << endl;
        //x_ = 100;  // 这样会报错
        return x_;
    }

    int GetX()
    {
        cout << "GetX ..." << endl;
        return x_;
    }
private:
    int x_;
}

int main(void)
{
    const Test t(10);
    t.GetX();

    Test t2(20);
    t2.GetX();
    return 0;
}

9、mutable

#include <iostream>
using namespace std;

class Test
{
public:
    Test(int x):x_(x)
    {
        
    }

    int GetX() const
    {
        cout << "const GetX ..." << endl;
        //x_ = 100;  // 这样会报错
        return x_;
    }

    int GetX()
    {
        cout << "GetX ..." << endl;
        return x_;
    }

    void OutPut() const
    {
        cout << "x = " << x_ << endl;
        outputTimes_++;
    }

    int GetOutputTimes() const
    {
        return outputTimes_;
    }
private:
    int x_;

    mutable int outputTimes_;
}

int main(void)
{
    const Test t(10);
    t.GetX();

    Test t2(20);
    t2.GetX();

    t.Output();
    t.Output();
    cout << t.GetOutputTimes() << endl;
    return 0;
}

10、const总结

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值