typename
typename
适用于在型别之前的标识符,如:
#include <iostream>
#include <vector>
using namespace std;
class Num{
public:
vector<int> num;
Num(){num.push_back(1),num.push_back(2);}
typedef int SubType;
};
template<class T>
class Myclass{
private:
int sum;
public:
Myclass(int _sum = 0):sum(_sum){ }
typename T::SubType Sum( T coll){
for(int i = 0;i <= 1;i++)
sum += coll.num[i];
return sum;
}
};
int main()
{
Num aa;
Myclass<Num> a(0);
cout << a.Sum(aa) << endl;
return 0;
}
如果不加typename
会出现
此处的typename
就是指出SubType
是class T
中的一个类型。
当然typename
还可以用来代替关键字class
。
template <typename T> class Myclass;
Member Template
成员模板,就是模板中再加入一个模板的声明余定义,如
#include<iostream>
using namespace std;
template <class T>
class Myclass {
private:
T value;
public:
Myclass(T _a) {
value = _a;
}
template<class X>
void assign(const Myclass<X>& x) {
cout << x.getValue() << endl;
}
T getValue()const {
return value;
}
};
int main() {
Myclass<double> d(1.2);
Myclass<int> i(11);
d.assign(d);
d.assign(i);
return 0;
}
其中的
Myclass<double> d(1.2);
Myclass<int> i(11);
d.assign(d);
d.assign(i);
d
与i
分别是double
类型与int
类型,然后再调用d.assign(d)
时,传入的时令T = double,X = double
,那么d.assign(d)
就能够正常调用内嵌模板函数template<class X> void assign(const Myclass<X>& x){ }
;此外d.assign(i);
令T = double,X = init
,也可正常调用函数。这就是内嵌模板的好处,两个类型之间可以自动转换,使用不同的内嵌模板函数。
但需要注意的是,当T != X
时,即两个类型不一样时,我们在Myclass
中的assign()
的参数x
和*this
的型别不一样,那么我们就不能够在assign()
中直接存取Myclass
的private与protected
成员,那么我们就只有另外加设一个函数,用于存取值,将上述代码实现中的
T getValue()const {
return value;
}
那么,其实这是因为assign()
中的不同类型变量仍然可以访问Myclass
中的public
变量或者函数。
基本型别的显式初始化
如果采用不含参数,明确的构造函数调用语法,基本型别会被初始化为0
,如:
#include<iostream>
using namespace std;
int main() {
int i = 3;
i = int();
cout << i << endl;
return 0;
}
执行结果
当然,这种功能更适用于模板函数中的初始化值,保证任何型别都有一个确切的初值,如
命名空间
namespace
将不同的标识符集合在一个具名的作用域内。如果在namespace
之内定义所有的标识符,那么namespace
本声名称就成为唯一可能于其他全局符号冲突的标识符。那么在标识符前加namespace
就可以应用namespace
中的符号,之间用::
隔开。
而namespace std
包含了其中的所有定义的标识符。
此外,using
的使用也很常见:一个using声明一次只引入一个命名空间成员,如:
#include<iostream>
using std::cout;
int main()
{
int x;
// cin >> x;//wrong
std::cin >> x;//right
cout << x;//right
return 0;
}
简写名字只能在声明它的作用域及其嵌套作用域中使用,一旦该作用域结束了,就必须使用完全限定名,如:
#include<iostream>
using namespace std;
namespace std{
void print(int i) {
cout << i << endl;
}
}
void print(float f) {
cout << f << endl;
}
int main()
{
using std::print;//嵌套使用
print(2.2);
print(1);
return 0;
}
explict
用于禁止单参数构造函数
用于自动类型转换,如
class Myclass{
explict Myclass(int num){ ... }
此时我们在如此调用就不行了,如
Myclass a = 12;
因为我们使用explict
禁止了自动转换调用构造函数。
注意区别一下两中操作
X x;
Y y(x);//显式调用
X x;
Y y = x;//隐式调用