C++ 如何转换;“正常”;C++;类到模板?
我试图将一个类从“普通”类转换为模板类,但我不理解正确的语法。下面是一个(大大简化的)示例,我从中开始。这是VisualStudio 2010,C++,针对X64架构,Windows 7。 目标是将类T重写为模板,以处理TEntry或新类OtherTEntry,其概念类似于TEntry,具有相同的成员函数,但具有不同的数据成员 我很感激你给我的建议。如果可能的话,我希望将头文件和实现文件分开。我特别关注对局部变量T*的引用,以及如何正确使用sizeof() 在文件T.h中:C++ 如何转换;“正常”;C++;类到模板?,c++,class,templates,C++,Class,Templates,我试图将一个类从“普通”类转换为模板类,但我不理解正确的语法。下面是一个(大大简化的)示例,我从中开始。这是VisualStudio 2010,C++,针对X64架构,Windows 7。 目标是将类T重写为模板,以处理TEntry或新类OtherTEntry,其概念类似于TEntry,具有相同的成员函数,但具有不同的数据成员 我很感激你给我的建议。如果可能的话,我希望将头文件和实现文件分开。我特别关注对局部变量T*的引用,以及如何正确使用sizeof() 在文件T.h中: class T {
class T
{
T(void);
T(G *pGIn, const unsigned long s, char nIn);
~T(void);
// Member functions
public:
bool Expand(const unsigned long newS);
void Empty(void);
private:
G *pG;
char n;
unsigned long s;
int f;
TEntry *p;
};
在TEntry.h文件中:
class TEntry
{
// Constructors
public:
TEntry();
TEntry(int l);
// Member functions
public:
void Relocate(int delta);
private:
// Data members
int k;
TEntry *p;
};
在文件T.cpp中:
T::T()
{
p=NULL; s=0; pG=NULL;
Empty();
return;
}
T::T(G *pGIn, const unsigned long m, char nIn)
{
pG=pG; n=nIn;
return;
}
T::~T(void)
{
if(p!=NULL)
delete[] p;
return;
}
bool T::Expand(const unsigned long newS)
{
T *pBefore=p;
p=(T *)_realloc_dbg(p, newS*sizeof(T), _NORMAL_BLOCK,__FILE__,__LINE__);
s=newS;
return p!=NULL;
}
void T::Empty()
{
f=0;
return;
}
在TEntry.cpp文件中:
T::T()
{
}
T::T(int i)
{
k=i;
}
void T::Relocate(int delta)
{
k+=delta;
return;
}
我希望将头文件和实现文件分开
虽然有可能做到这一点,但这有点像一场噩梦。通常最好将模板的所有部分放在一起
您可能想要的是这样的:
template< typename TYPE > class T
{
// ...
TYPE* p;
};
templateclass T
{
// ...
*p型;
};
然后可以使用sizeof(TYPE)
有一件事你不能做,也永远不应该做的就是将realloc与new和delete混合。C++不支持重新分配新的和删除的内存。相反,它有一些容器,比如为您管理内存的std::vector
而且,如前所述,一个字母的类和变量名称不是一个好主意。:) 最简单的方法是从一个完整的、有效的、非模板版本的
T
开始,该版本是按照您以后希望在模板中使用的类型之一编写的(这里的明显选择是:TEntry
)
一旦有了一个工作的实现,就可以将其转换为模板
U
U
)替换T
中出现的所有TEntry
)T
的类定义中:
template <class U>
class T {
//...
#include
指令间接)。模板不支持单独编译头文件和源文件通常,最好将模板代码保存在.h文件中。如果绝对必要,可以将实现放在.cpp文件中,有关详细信息,请参阅第6章 你可以这样做(减少不太重要的细节):
模板
你的班级
{
YourClass()
:p(空)、s(0)、pG(空)
{
空();
}
YourClass(G*pGIn,常量无符号长s,字符nIn)
{
//…在这里执行
}
~YourClass()
{
如果(p!=NULL)
删除p;
}
公众:
bool Expand(const unsigned long newS)
{
T*pBefore=p;
p=(T*)realloc\u dbg(p,newS*sizeof(T),\u NORMAL\u BLOCK,\uuuuuuuuu文件,\uuuuuuuu行);
s=新闻;
返回p!=NULL;
}
私人:
G*pG;
字符n;
无符号长s;
int f;
T*p;
};
几点注意:
- 将类模板命名为
确实是个坏主意,因为使用T
作为模板参数名称是一种常见做法T
- 关于
,在您的代码示例中,它不应用于模板,而是应用于普通类,无论如何,在类、类模板或模板参数上使用sizeof
应该不会有任何问题sizeof
std::vector
?请放心,我的实际类并没有命名为T。我现在有一对完整的工作类,但我只显示了代码的一小部分,足以询问我的问题我必须检查一下ReLoCo的用法。在VisualStudio中,“new”操作符使用Maloc。不管它可能在内部使用什么,也可能不在内部使用。你不能安全地混合C(MalcC/ReloLC/Free)和C++(new /Delphi)。内存分配策略。混合使用它们有什么不安全之处?在这种情况下,可移植性不是问题。谢谢你,这个评论非常有用。我已经有了T和TEntry的工作实现。至于“单独编译”,这不是我的目标,只是单独的文件。#include的作用是将头文件与实现文件结合起来。
template <class U>
«return type» T<U>::«member specification» //...
template <class T>
class YourClass
{
YourClass()
: p(NULL), s(0), pG(NULL)
{
Empty();
}
YourClass(G *pGIn, const unsigned long s, char nIn)
{
// ... implementation here
}
~YourClass()
{
if(p!=NULL)
delete p;
}
public:
bool Expand(const unsigned long newS)
{
T *pBefore=p;
p=(T *)_realloc_dbg(p, newS*sizeof(T), _NORMAL_BLOCK,__FILE__,__LINE__);
s=newS;
return p!=NULL;
}
private:
G *pG;
char n;
unsigned long s;
int f;
T* p;
};