C++学习 Day.9(宏和模板简介)

好久没更了,摆还是爽

遗留问题:

(16条消息) int&作为函数返回类型-编程语言-CSDN问答(已解决)

宏:

预处理器编译指令都以#打头 

#define(宏常量)使得预处理器进行文本替换,而不考虑其他,编译器将检查文本正确与否。    不解风情

 宏需要大量括号,凡变量尽量都打一括号。

列如:

#define i* int*
i* a,b;
此时我们的本意是   int *a,*b;
而实际上的代码为   int *a, b;
此时的 b 为 int 型,而非 int* 型

使用宏避免多次包含

reference:

(6条消息) #ifndef,#define,#endif的作用和用法_Junzheng Li的博客-CSDN博客

(7条消息) #ifndef/#define/#endif使用详解_ 司 的博客-CSDN博客_#ifndef _a_h_

例:

 assert宏:验证表达式

语法:

assert (expression that evaluates to true or false);

包含:于<assert.h>头文件

示例:

#include <assert.h> 
int main() 
{ 
 char* sayHello = new char [25]; 
 assert(sayHello != NULL); // throws a message if pointer is NULL 
 // other code 
 delete [] sayHello; 
 return 0; 
}

在我的DEV编译器中出现如下报错:

注: 

 宏不支持任何形式的类型安全,这是一个严重的缺点。另外,复杂的宏调试起来也不容易

 模板:

template:n. 样板;模板;型板

声明模板以关键字template打头 

//模板类,使用需要<type>
template <typename T/*可多写*/> 
class HoldVarTypeT 
{ 
private: 
 T value; 
public: 
 void SetValue (const T& newValue) { value = newValue; } 
 T& GetValue() {return value;} 
};

 instantiation :实例化

template <typename T1, typename T2> 
class HoldsPair 
{ 
private: 
 T1 value1; 
 T2 value2; 
public: 
 // Constructor that initializes member variables 
 HoldsPair (const T1& val1, const T2& val2) 
 { 
 value1 = val1; 
 value2 = val2; 
 }; 
 // ... Other member functions 
};

 实例化:

HoldsPair <int, double> pairIntDouble (6, 1.99);
HoldsPair <int, int> pairInts (6, 500);
声明包含默认参数的模板

可以修改前面的 HoldsPair < > ,将模板参数的默认类型指定为 int
template <typename T1=int, typename T2=int>
class HoldsPair
{
// ... method declarations
};
这与给函数指定默认参数值极其类似,只是这里指定的是默认类型。

这样,前述第二种 HoldsPair 用法可以简写为:

// Pair an int with an int (default type)
HoldsPair <> pairInts (6, 500);
#include <iostream>
using namespace std;

template <typename T1 = double, typename T2 = int >
class HoldsPair {
	private:
		T1 value1;
		T2 value2;
	public:
		HoldsPair(const T1& val1, const T2& val2) // constructor
			: value1(val1), value2(val2) {}

		// Accessor functions

		const T1& GetFirstValue() const {
			cout << "fanhui double " << value1 << endl;
			return value1;
		}
		const T2& GetSecondValue() const;
		//如果这两个函数不给出定义,则无返回,出现return 1;的报错
};

// specialization of HoldsPair for types int & int here
template<> class HoldsPair<int, int> {
	private:
		int value1;
		int value2;
		string strFun;
	public:
		HoldsPair(const int& val1, const int& val2) // constructor
			: value1(val1), value2(val2) {}

		const int & GetFirstValue() const {
			cout << "Returning integer " << value1 << endl;
			return value1;
		}
};

int main() {

	HoldsPair<int, int> pairIntInt(222, 333); //在类型为int,int时调用第二个,否则调用第一个
	pairIntInt.GetFirstValue();

	return 0;
}

模板类的具体化,如上。

模板类和静态成员

示例代码:

#include <iostream>
using namespace std;

template <typename T>
class TestStatic {
	public:
		static int staticVal;
};

// static member initialization
template<typename T> int TestStatic<T>::staticVal;

int main() {
	TestStatic<int> intInstance;
	cout << "Setting staticVal for intInstance to 2011" << endl;
	intInstance.staticVal = 2011;

	TestStatic<double> dblnstance;
	cout << "Setting staticVal for Double_2 to 1011" << endl;
	dblnstance.staticVal = 1011;

	cout << "intInstance.staticVal = " << intInstance.staticVal << endl;
	cout << "dblnstance.staticVal = " << dblnstance.staticVal << endl;

	return 0;
}

Q:静态变量有啥用?

假定您要编写一个将两个值相加的通用函数,为此可编写下面这样的模板函数 Sum()
template <typename T1, typename T2, typename T3>
void Sum(T1& result, T2 num1, T3 num2)
{
result = num1 + num2;
return;
}
 

想要加上不同的值应如下进行编码:参变量可变的模板

#include<iostream>
using namespace std;

template<typename R,typename V>
void Sum(R& result,V& val){
	result+=val;
	cout<<"i have in prime"<<endl;
}

template<typename R, typename First, typename...Rest>
void Sum(R& result, First val1, Rest...valN) {
	result += val1;
	return Sum(result, valN...);
}

int main() {
	double dResult = 0;
	Sum(dResult, 3.14, 4.56, 1.1111);
	cout<<"dResult"<<dResult<<endl;
	
}

注:必须要有基础模板

实例化并使用 std::tuple

引用:(3条消息) C++的get()函数使用详解_Nine_CC的博客-CSDN博客_c++ get

使用static_assert();

static_assert C++11 新增的一项功能,让您能够在不满足指定条件时禁止编译。这好像不可思议,但对模板类来说很有用。例如,您可能想禁止针对 int 实例化模板类,为此可使用 static_assert ,它是一 种编译阶段断言,可用于在开发环境(或控制台中)显示一条自定义消息:
static_assert(expression being validated, "Error message when check fails");
要禁止针对类型 int 实例化模板类,可使用 static_assert( ) ,并将 sizeof(T) sizeof(int) 进行比较,如果它们相等,就显示一条错误消息:
static_assert(sizeof(T) != sizeof(int), "No int please!");

如图:

DEV编译器报错为: 

学习本章介绍的模板知识后,便为学习如何使用 STL 做好了准备!

问:在头文件中,为何要防范多次包含?
答: 多次包含防范使用 #ifndef #define #endif ,可避免头文件出现多次包含或递归包含错误,有时还可提高编译速度。
问:如果所需的功能使用宏函数和模板都能实现,在什么情况下应使用宏函数,而不是模板?
答: 在任何情况下都应使用模板,而不是宏函数,因为模板不但提供了通用实现,还是类型安全
的。宏函数不是类型安全的,最好不要使用。
问:调用模板函数时,需要指定模板参数类型吗?
答: 通常不需要,因为编译器能够根据函数调用使用的实参推断出模板参数类型。
问:对于特定模板类,每个静态成员有多少个版本?
答: 这完全取决于针对多少种类型实例化了该模板类。如果针对 int string 和自定义类型 X 实例
化了该模板类,则每个静态成员都有三个不同的版本 每种模板实例化一个。

编写模板函数Display,它可调用不同数量和类型的的参数并显示。

#include<iostream>
using namespace std;

template<typename t0>
void Display(t0& e0) {
	cout << "different from xiamian de , i will be used when the en is used\
 that's to say , the element en won't be used int this case" << endl;

}


template<typename t0,  typename ...other>
void Display(t0& e0, other...en) {
	cout << e0 << endl;
	return Display(en...);
}

int main() {
	string a = "fu huo ba", b = "wo";
	string c = "de", d = "ai", f = "ren";
	Display(a, b, c, d, f, "hhh");
	return 0;
}

 运行结果:

 

一版和上面稍有不同的代码:

#include<iostream>
using namespace std;

void Display() {
	cout << "i will be use at last,when all the elements are use\
 even Display(en)" << endl;
}

template<typename t0,  typename ...other>
void Display(t0& e0, other...en) {
	cout << e0 << endl;
	Display(en...);
}

int main() {
	string a = "fu huo ba", b = "wo";
	string c = "de", d = "ai", f = "ren";
	Display(a, b, c, d, f, "hhh");
	return 0;
}

运行结果: 

 

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值