重要提示:这个问题已经很长了,如果这是你第一次阅读这篇文章我建议你从底部开始,因为解决方案是在一个回合的方式,但代码有点臭.
阅读完模板教程后,我能够更改现有类以支持泛型类型.但是,许多对象已经依赖于此,所以我正在寻找一种使方法通用而不是整个类的方法.
我尝试了以下内容,但看起来不支持此行为.
// foobar1.h
// Don't want the entire class to be generic.
//template<class T>
class FooBar1
{
public:
template<class T> T Foo();
}
// foobar2.h
class FooBar2 : public FooBar1
{
}
// foobar1.cpp
template<class T>
T FooBar1::Foo()
{
return something;
}
// test.cpp
FooBar1 fb1;
FooBar2 fb2 = fb1.Foo<FooBar2>();
Run Code Online (Sandbox Code Playgroud)
这应该不起作用,还是我在其他地方遇到的一个错误?
未定义的引用
FooBar2 Foo<FooBar2>()
为了实现我想要实现的目标,我在C#中如何做到这一点......
public class FooBar1
{
public T Foo<T>()
where T : FooBar1
{
return something;
}
}
public class FooBar2 : FooBar1 { }
FooBar1 fb1 = new FooBar1();
FooBar2 fb2 = fb1.Foo<FooBar2>();
Run Code Online (Sandbox Code Playgroud)
有什么方法可以做类似于C++的东西吗?
刚刚纠正了一些小的语法细节(我的意思是让Foo公开,然后返回T,而不是FooBar2).仍然得到编译器错误...当我删除模板行为时,错误消失了,到目前为止答案说我正在做的是有效的...但如果是,那么为什么我仍然得到错误?谢谢你的回答!
Josh,这是实际的源代码(嗯,我认为是相关的,anwyay - 如果你认为我已经跳过了重要的一点,请告诉我).
// ImageMatrix.h
class ImageMatrix : public VImage
{
public:
// ... various functions ...
template<class T> T GetRotatedCopy(VDouble angle);
}
// ImageFilter.h
class ImageFilter : public ImageMatrix
{
// ... various functions ...
}
// ImageMatrix.cpp
template<class T>
T ImageMatrix::GetRotatedCopy(VDouble angle)
{
// ... create a new instance of ImageMatrix and return it.
}
// ImageProcessor.cpp
ImageFilter filter2 = filterPrototype.GetRotatedCopy<ImageFilter>(90);
Run Code Online (Sandbox Code Playgroud)
这是实际的编译器错误:
/home/nick/Projects/ViMRID/vimrid/Debug/libvimrid.so:vimrid :: imaging :: processing :: ImageFilter vimrid :: imaging :: ImageMatrix :: GetRotatedCopy(double)'的未定义引用
顺便说一下,除了实现线之外的所有东西都位于一个库中; 所以它是从一个单独的二进制文件调用的......这有关系吗?更正; 它都在同一个图书馆里.但是所有块都是不同的文件.
当我注释掉实现行(ImageFilter filter2 = filterPrototype ...)时,它构建得很好,所以看起来就是这一行导致它......
还有问题......这可能是命名空间的问题吗?抓紧,好吧,我现在已经掌握了模板的概念!:)模板定义必须与声明一起在标题中(对吗?) - 所以现在我已经将声明移到了ImageMatrix.h,所有内容都编译完成.但是,我不得不使用dynamic_cast它来使它工作; 这是正确的吗?如果我要离开,请纠正我!
// This is in the header file!
// Help!!! This looks really really smelly...
template<class T>
T ImageMatrix::GetRotatedCopy(VDouble angle)
{
ImageMatrix image = _getRotatedCopy(angle);
ImageMatrix *imagePtr = ℑ
return *dynamic_cast<T*>(imagePtr);
}
Run Code Online (Sandbox Code Playgroud)
参考更新5,当我不使用dynamic_cast时......
template<class T>
T ImageMatrix::GetRotatedCopy(VDouble angle)
{
ImageMatrix image = _getRotatedCopy(angle);
ImageMatrix *imagePtr = ℑ
//return *dynamic_cast<T*>(imagePtr);
return *imagePtr;
}
Run Code Online (Sandbox Code Playgroud)
......我收到这个错误......
../src/imaging/processing/../ImageMatrix.h: In member function ‘T vimrid::imaging::ImageMatrix::GetRotatedCopy(vimrid::VDouble) [with T = vimrid::imaging::processing::ImageFilter]’:
../src/imaging/processing/ImageProcessor.cpp:32: instantiated from here
../src/imaging/processing/../ImageMatrix.h:45: error: conversion from ‘vimrid::imaging::ImageMatrix’ to non-scalar type ‘vimrid::imaging::processing::ImageFilter’ requested
make: *** [src/imaging/processing/ImageProcessor.o] Error 1
Run Code Online (Sandbox Code Playgroud)
另外,如果我在更新6中没有使用所有那些臭臭的代码......
class ImageMatrix : public VImage
{
public:
template<class T> T GetRotatedCopy(VDouble angle);
private:
ImageMatrix _getRotatedCopy(VDouble angle);
};
template<class T>
T ImageMatrix::GetRotatedCopy(VDouble angle)
{
return _getRotatedCopy(angle);
}
Run Code Online (Sandbox Code Playgroud)
...我得到了与更新6中相同的错误.
Ecl*_*pse 11
是的,你非常接近,试试这个:
class FooBar1
{
public:
template<class T> T Foo();
};
class FooBar2 : public FooBar1
{
};
template<class T>
T FooBar1::Foo()
{
return T();
}
int main()
{
FooBar1 fb1;
FooBar2 fb2 = fb1.Foo<FooBar2>();
}
Run Code Online (Sandbox Code Playgroud)
您遇到的问题是您指定的返回类型为FooBar1::Foo()as FooBar2,您应该将其设置为just T.
如果你想为FooBar2做特定的事情,你可以专门研究FooBar2:
template<>
FooBar2 FooBar1::Foo<FooBar2>()
{
return FooBar2();
}
Run Code Online (Sandbox Code Playgroud)
编辑:听起来你在编译器没有找到模板化GetRotatedCopy的定义时遇到问题.C++中的模板相当挑剔,通常的做法是将整个模板实现放在头文件中.你可以试试这个:
class ImageMatrix : public VImage
{
public:
// ... various functions ...
template<class T> T GetRotatedCopy(VDouble angle)
{
// ... create a new instance of ImageMatrix and return it.
}
};
Run Code Online (Sandbox Code Playgroud)
编辑:我找不到gcc文档,但这里是microsoft关于显式模板实例化和库的文档,它给出了一些关于发生了什么的想法.您可能希望按照我之前的建议在头中包含实现,或者在库中调用GetRotatedCopy,或者在库中显式实例化它.有关语法,请参阅下面的veefu答案.
这与C#的不同之处在于,与C#不同,C++中的模板实际上为每个不同的模板参数组合创建了一个全新的类/函数.例如,vector<int>是一个完全不同的类(使用不同的编译方法集)vector<string>.请参阅凯文的答案以获得更好的解释.
至于当你不使用模板时错误消失,这实际上并没有告诉你多少,因为直到你实际实例化一个模板,它不会
RE更新5,6,7
您的dynamic_cast不起作用,只有当指针实际指向您要转换的类的实例时,才能使用它.(它与asC#中的运算符类似).
我现在怀疑,你想要的是CRTP.您从ImageFilter的实例开始,并希望在其上使用基类方法,并获取ImageFilter的新副本.尝试这些方面:
template <class T>
class ImageMatrix
{
public:
T GetRotatedMatrix()
{
return T();
}
};
class ImageFilter : public ImageMatrix<ImageFilter>
{
};
int main()
{
ImageFilter filterPrototype;
ImageFilter otherFilter = filterPrototype.GetRotatedMatrix();
}
Run Code Online (Sandbox Code Playgroud)
否则,如果您真的想从ImageMatrix开始并将其转换为ImageFilter,则必须在ImageFilter上添加一个构造函数,该构造函数采用ImageMatrix.
| 归档时间: |
|
| 查看次数: |
2260 次 |
| 最近记录: |