美文网首页
【C++】C++学习笔记之十:类模板,函数模板及其他

【C++】C++学习笔记之十:类模板,函数模板及其他

作者: Angeladoudou | 来源:发表于2016-10-17 17:05 被阅读0次

    static 与 this 指针

    static

    当类被多次实例化后,一般数据成员会有多份,而成员函数只有一份,通过this指针确定当前数据成员是在那个对象中被调用。但是类中的static成员却不尽相同:

    static成员数据

    类中的static数据成员,在类中只有一份,可以理解成,类范围内的静态全局变量。
    类中的static数据成员必须在类外定义并初始化,类中声明。
    就像静态变量,类中的static数据成员也只初始化一次,并在整个程序的声明周期中一直存在。

    static成员函数

    类的static成员函数,与普通成员函数不同,它被调用时不会传递this指针,也就是说他没有对象的概念。
    类中的static成员函数,只能使用类中的static数据成员。(因为没有this指针不能确认那个普通数据成员可以使用)
    static成员函数的调用方式有两种:
    1.通过对象调用
    2.通过class name调用

    class complex{
        private:
            double re, im;
            static int instance_cnt;
        public:
            complex(double _re = 0, double _im = 0) : re(_re), im(_im) {  instance_cnt++; }
            complex(const complex & c):re(c.re), im(c.im) { instance_cnt++; }
            static int get_instance_num(){ return instance_cnt; } //返回当前类共有多少对象
    };
    int complex::instance_cnt = 0;
    
    int main(){
        complex c1(1,2);
        complex c2(c1);
        complex c3 = c2;
        complex *pc = new complex(2,3);
        cout << "complex class has " << complex::get_instance_num() << " objects in total." << endl;//通过类名调用
        delete pc;
        pc = NULL;
        cout << "now the complex class has " << c1.get_instance_num() << " objects left." << endl;//通过类对象调用
    }
    

    以上运行结果:

    Paste_Image.png

    注:static 成员数据在类外定义的时候不需要使用static关键字:

    Paste_Image.png

    this指针

    类的成员函数都有一个隐藏的参数——this指针,当数据成员被调用时都会隐式传入this指针。但是,对于类中的static成员函授,不会传入this指针,所以static成员函数无法处理对象的成员数据,而只能处理类中的static数据。

    Paste_Image.png

    放在private区中的constructor函数(singleton)

    类的构造函数通常为public,这样才能构造出很多实例。但是,在设计模式中有一种专门把构造函数设计成私有成员,其作用就是保证一个类只能有一个实例,并提供一个全局唯一的访问点。这种设计模式叫做单例设计模式(singleton)

    class Singleton{
        public:
            static Singleton* getInstance(){  
                if(!pIns){
                    pIns = new Singleton();
                }
                return pIns ; 
            }
            static void dosth(){……}
            static void destory(){
                if(pIns){
                    delete pIns;
                    pIns = NULL;
                }
            }
        private:
            singleton(){}
            static singleton * pIns;
    };
    
    //调用:
    int main(){
        for(int i = 0; i < 10; ++i){
            Singleton *ps  = Singleton::getInstance();//通过全局访问点访问,其实只有一个实例,并不是每次循环都创建
            Singleton::dosth();
        }
        Singleton::destroy();
        return 0;
    }
    

    singleton的特点:
    不调用getInstance就没有Singleton类的实例存在,调用一次后,不管再调用多少次,都只有一个实例。

    cout——一种ostream,重载了“<<”操作符

    cout是一种ostream类,在其内部针对各种内置数据类型多次重载了操作符“<<”,使其可以输出内置数据类型的各种实例。因此用户定义的类中,如果想重载操作符"<<",必须定义成全局的操作符重载函数,第一个参数是ostream cout,第二个参数是自定义的类,这样才符合cout 在 “<<”左边,实例在右边的日常使用习惯。

    cout类的内部实现

    complex类,重载操作符“<<”的代码示例:

    class complex{
    private:
        double re, im;
    public:
        friend ostream & operator<<(ostream & os, const complex& c);
    };
    
    ostream & operator<<(ostream & os, const complex& c){
        os << "(" << c.re << "," << c.im << ")" ;
        return os;
    }
    
    int main(){
        complex c1(1,2);
        cout << c1 << endl;
    }
    

    如果把操作符“<<”的重载设计成类成员函数,则其参数将只能有一个ostream类型,在调用的时候会默认出入this指针作为左值,这样对其的调用形式将是:“c1 << cout”,是不是很奇怪呢?完全不符合我们日常的使用习惯。
    因此切记:对于自定义的类,其操作符“<<”的重载函数必须要写成全局变量才好!

    类模板与函数模板

    类模板

    使用时必须显示指定类型

    类模板的定义和使用

    函数模板

    使用时编译器会作参数推导,不用显示指定类型

    函数模板参数推导

    namespace

    几种使用命名空间方式

    使用命令的方式引用

    语法:using namespace <名字空间名>

    使用声明的方式引用

    语法:using <名字空间名>::<函数名>

    不使用using引用

    语法:在使用的地方,直接以 <名字空间名>::<函数名> 的方式使用

    相关文章

      网友评论

          本文标题:【C++】C++学习笔记之十:类模板,函数模板及其他

          本文链接:https://www.haomeiwen.com/subject/yqkgyttx.html