3

我是新来的模板在C++中。 任何人都可以解释为什么我的专业构造函数永远不会被执行。 它在我删除const和引用操作符时起作用。专业模板类构造函数

#include<iostream> 
#include<string> 

using namespace std; 

template<typename T> 
class CData 
{ 
public: 
    CData(const T&); 
    CData(const char*&); 
private: 
    T m_Data; 
}; 

template<typename T> 
CData<T>::CData(const T& Val) 
{ 
    cout << "Template" << endl; 
    m_Data = Val; 
} 
template<> 
CData<char*>::CData(const char* &Str) 
{ 
    cout << "Char*" << endl; 
    m_Data = new char[strlen(Str) + 1]; 
    strcpy(m_Data, Str); 
} 

void main() 
{ 
    CData<int> obj1(10); 
    CData<char*> obj2("Hello"); 
} 

输出是

模板

模板

+1

'main'必须返回'int',而不是'void'。此外,'strcpy'和'strlen'的头文件是'',而不是''。 – dyp 2014-08-27 13:50:13

+2

字符串文字是一个数组左值,可以将其转换为指针prvalue。指针prvalue不能绑定到非常量左值引用,如'const char *&'。这就是为什么第一个ctor被调用的原因。 – dyp 2014-08-27 13:52:32

+1

顺便说一句,这不是一个部分专业化。它是一个单一成员函数的显式专业化。 – dyp 2014-08-27 13:56:45

回答

5

因为你不能绑定"Hello"const char*&

在注释中添加的信息dyp是相当有趣:

字符串文字是一个数组左值,其可以被转换为指针prvalue。指针prvalue不能绑定到像为const char一个非const左值参考* &

这意味着你实际上可以使更换const char*&通过const char* const&工作,或者在C++ 11甚至const char* &&,不知道这但在你的用例中真的很聪明。

+0

*“这意味着你可以真正使它工作”*或者你只是使用'const char *'而没有任何引用。不过,我不确定OP的意图。 – dyp 2014-08-27 14:05:38

+0

@Drax匹配模板声明,你应该使用'char * const&'。 – 2014-08-27 14:27:24

2

UPDATE我把一切都错了,完全改写了答案。

首先,这个构造

template<> 
CData<char*>::CData(const char* &Str) 

不是CData(const T&)一个特例,因为这里的Str参数是非const引用的指针的const char。所以它是非模板构造函数CData(const char*&)的定义。

其次,"Hello"的类型为“n const char”(见What is the type of string literals in C and C++?),因此它不能转换为非const引用。这就是为什么“模板”构造函数被调用。

正确专业化是

template<> 
CData<char*>::CData(char* const& Str) 

即,它接受一个常量引用char*

之后,你应该删除CData(const char*&),除非你需要例如该代码编译:

const char* foo = "foo"; 
CData<int> obj2(foo); 

所以这里是代码:

template<typename T> 
class CData 
{ 
public: 
    CData(const T&); 
private: 
    T m_Data; 
}; 

template<typename T> 
CData<T>::CData(const T& Val) 
{ 
    .... 
} 

template<> 
CData<char*>::CData(char* const& Str) 
{ 
    .... 
} 

// warning: deprecated conversion from string constant to 'char*' 
CData<char*> obj2("Hello"); // calls CData(char* const&) 

上述警告固定的正确方法是添加另一种专业化:

template<> 
CData<const char*>::CData(const char* const& Str) 
{ 
    ... 
} 

CData<const char*> obj2("Hello"); // calls CData(const char* const&) 
+0

@dyp谢谢,我纠正了答案。关于链接,C++字符串文字也覆盖在那里。 – 2014-08-27 14:11:30

+0

哦,哎呀,我只读了一半的第一个答案,并瞥了其他人。 – dyp 2014-08-27 14:12:15