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

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引用

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

最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
【社区内容提示】社区部分内容疑似由AI辅助生成,浏览时请结合常识与多方信息审慎甄别。
平台声明:文章内容(如有图片或视频亦包括在内)由作者上传并发布,文章内容仅代表作者本人观点,简书系信息发布平台,仅提供信息存储服务。

相关阅读更多精彩内容

  • 前言 把《C++ Primer》[https://book.douban.com/subject/25708312...
    尤汐Yogy阅读 13,166评论 1 51
  • 第一章 计算机与C++编程简介 C++程序6个阶段编程 ->预处理->编译->连接->装入->执行1.程序在编译器...
    rogertan30阅读 9,876评论 0 1
  • 第一天 一.内联函数(inline) 函数调用的时候需要建立栈内存环境,进行参数传递,并产生程序执行转移,这些工作...
    陈果123阅读 4,849评论 0 1
  • 只有当一个人独处的时候,他才可以完全成为自己。
    为了追求不自量力阅读 2,241评论 0 1
  • 拥有愿景,使命和价值观,可以网聚天下志同道合之士,可以提高凝聚力,在遇到眼前困难时不至于人心涣散。 作为个人,要记...
    423429d90f38阅读 1,522评论 0 0

友情链接更多精彩内容