static ,auto ,template的一个小例子

#include <iostream>
class Foo
{
public:
	static int get(void)
	{
		return 0;
	}
};
class Bar
{
public:
	static const char* get(void)
	{
		return "0";
	}
};
template <class A>
void func(void)
{
	auto val = A::get();

	//...
}
int main(void)
{
	func<Foo>();
	func<Bar>();

	system("pause");
	return 0;
}

 

 

//1.关于static

/*此部分来源于https://www.cnblogs.com/songdanzju/p/7422380.html*/
(1)全局静态变量在声明他的文件之外是不可见的,准确地说是从定义之处开始,到文件结尾(隐藏)
例如a.cpp中static int i=0;在main.cpp中包含a.h也不能发现i;
(2)static的第二个作用是保持变量内容的持久。(static变量中的记忆功能和全局生存期)    
               

#include <stdio.h>
 
int fun(){
    static int count = 10; 
    return count--;
}
 
int count = 1;
 
int main(void)
{
     printf("global\t\tlocal static\n");
     for(; count <= 10; ++count)
               printf("%d\t\t%d\n", count, fun());
     return 0;
}


         //存储在静态数据区的变量会在程序刚开始运行时就完成初始化,也是唯一的一次初始化。共有两种变量存储在静态存储区:全局变量和static变量,只不过和全局变量比起来,static可以控制变量的可见范围(只能在fun()函数范围内看到count)在第一次进入这个函数的时候,变量count 被初始化为10!并接着自减1,以后每次进入该函数,count 就不会被再次初始化了,仅进行自减1的操作;在static发明前,要达到同样的功能,则只能使用全局变量。
(3)static的第三个作用是默认初始化为0(static变量)
(4)static的第四个作用:C++中的类成员声明static

(1)首先静态成员可以是public的,也可以是private的,只需在一般的变量、函数声明语句前加上static关键字即可声明一个static变量。

(2)static不会想普通类数据成员一样每一个类对象都有一份,全部类对象是共享一个static类成员的,例如A类对象修改了static成员为1,那么B对象对应的static类对象成员的值也会是。注意:static类对象必须要在类外进行初始化


class Text
{
	public:	static int count;

};
int Text::count=0;//用static成员变量必须要初始化 
int main()
{
	Text t1;
	cout<<t1.count<<endl; 
	return 0;
}//程序输出0

 

(3)由于static修饰的类成员属于类,不属于对象,因此static类成员函数是没有this指针的,this指针是指向本对象的指针。正因为没有this指针,所以static类成员函数不能访问非static的类成员,只能访问 static修饰的类成员


class Text
{
	public:
	static int fun()
	{
		return num;
	}
	static int count;
	int num;
};
int Text::count=5;//用static成员变量必须要初始化 
int main()
{
	Text t1;
	Text t2;
	t1.num=100;
        t1.fun();//发生错误,fun函数return的是非static类成员 如果return count就正确 
	return 0;

}

//2.关于template

模板有两类,函数模板和类模板(C++14开始出现了变量模板,不过不在此讨论)。如果想要生成函数代码,则需要用函数模板,如果想要生成类定义,则需要用到类模板。

1.函数模板

#include <iostream>
template<typename T>
T add(T x, T y)
{
    return x + y;
}
int main()
{
    int x1 = 0, y1 = 1;
    auto result1 = add(x1, y1);
    std::cout << result1 << std::endl;
    float x2 = 0.0f, y2 = 1.0f;
    auto result2 = add(x2, y2);
    std::cout << result2 << std::endl;
    return 0;
}
template<typename T, int i>
T create()
{
    T value();
    return value + i;
}

int main()
{
    float f1 = create<float, 1>();    // f1 == 1.0
    float f2 = create<float, 2>();    // f2 == 2.0
}

   我们总结一下函数模板的语法,模板定义由template关键字开始,后面跟着一对尖括号,尖括号里面是模板形参列表,也就是模板的参数。模板形参列表的写法和函数形参列表的写法是很相似的。都是“类型 参数名, 类型 参数名, ...”这种形式。上面的例子中,模板形参列表就是“typename T, int i”。我们注意到,模板形参列表需要为每个形参指定一个类型,这个是因为形参不一定是C++类型,还可以是具体的值,例如数字,指针等等。如果形参是一个类型,则需要使用typename关键字来表示形参的类型,如果形参是一个值,则需要写上这个值的类型。在使用模板的时候,要在模板的名字后面加一对尖括号,尖括号里面是模板实参列表,在上面的例子中,实参列表就是“float, 1”和“float, 2”。与函数调用类似,使用模板的时候编译器会检查实参列表的类型与形参列表的类型是否匹配,不匹配的话会报错。

2.类模板

在很多使用场合下,一个类会被使用很多次,用的时候呢也发现很多重复的地方,只有它的数据类型不同,这个时候就要用到类模板。


链接:https://www.jianshu.com/p/70ca94872418
template <typename T>
class Complex{    
public:
    //构造函数
    Complex(T a, T b)
    {
        this->a = a;
        this->b = b;
    }
    //先要理解class的意思。class应该理解为一种类型,象int,char一样,是用户自定义的类型。用这个类型可以来声明一个变量,比如int x, myclass my等等。这样就像变量x具有int类型一样,变量my具有myclass类型。理解了这个,就好解释this了,my里的this 就是指向my的指针。如果还有一个变量myclass mz,mz的this就是指向mz的指针。 这样就很容易理解this 的类型应该是myclass *,而对其的解引用*this就应该是一个myclass类型的变量。
//通常在class定义时要用到类型变量自身时,因为这时候还不知道变量名(为了通用也不可能固定实际的变量名),就用this这样的指针来使用变量自身。 
    //运算符重载
    //在一个类中,方法名相同而参数不同的几个方法,但是不能靠返回类型来判断
    //重载加法运算符用于类成员变量相加
    Complex<T> operator+(Complex &c)
    {
        Complex<T> tmp(this->a+c.a, this->b+c.b);
        return tmp;
    }     
private:
    T a;
    T b;
}
int main()
{
    //对象的定义,必须声明模板类型,因为要分配内容
    Complex<int> a(10,20);  
    Complex<int> b(20,30);
    Complex<int> c = a + b;  
    return 0;
}

//关于auto

1.用于代替冗长复杂、变量使用范围专一的变量声明。

#include<string>
#include<vector>
int main()
{
    std::vector<std::string> vs;
    //for (std::vector<std::string>::iterator i = vs.begin(); i != vs.end(); i++)
    for (auto i = vs.begin(); i != vs.end(); i++)
    {
        //..
    }
}

时刻要注意auto并不是一个真正的类型。auto仅仅是一个占位符,它并不是一个真正的类型,不能使用一些以类型为操作数的操作符,如sizeof或者typeid。

 

 

 

      

 

 

 

 

 


 

 

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值