具有编译时已知参数的纯虚拟成员函数?
Pure Virtual member function with compile-time known parameter?
我正在通过尝试为 STL 容器实现一个类型擦除模式来练习类型擦除模式,但我坚持使用这些容器的纯虚拟成员函数。我不知道如何实现作为接口的类型擦除模式的 "concept",保存被擦除类型共享的纯虚拟成员函数。像 Push 这样的函数需要一个编译时已知的参数。据我了解,虚函数不能使用auto或模板化,那么我该如何编写接口?
我试过用关键字'typename'告诉编译器稍后会给出类型,但是编译不通过
这是我目前对 'concept' 界面的了解:
class Concept{
public:
virtual void push(typename T val) = 0;
virtual typename T pop() = 0;
};
目前收到的错误是这样的:
error: expected nested-name-specifier before ‘T’ virtual void push(typename T val) = 0;
^
error: expected ‘,’ or ‘...’ before ‘val’ virtual void push(typename T val) = 0;
^~~
error: expected nested-name-specifier before ‘T’ virtual typename T pop() = 0;
如果有人能就此给我一些建议,我将不胜感激。预先感谢大家的热心帮助和宝贵时间。
typename 关键字只能是模板声明的一部分。
template <typename T> class Concept{
public:
virtual void push(T val) = 0;
virtual T pop() = 0;
};
你脑子里混合了模板和纯虚函数。第一个是编译时间,第二个是运行时间.
模板让您避免为不同的数据类型重复代码,其中纯虚拟成员函数允许您使用从同一类型继承的不同多态接口。 Type erasure 也与虚拟成员函数无关。两个完全不同的东西。
一旦上面的模板被实例化,比如说,int
,那么它就等于:
class Concept{
public:
virtual void push(int val) = 0;
virtual int pop() = 0;
};
现在这个class是抽象的;你不能实例化它,但你可以继承:
class f1 : public Concept {
public:
virtual void push(int val) { ... define it }
virtual int pop() { ... define it}
};
class f2 : public Concept {
public:
virtual void push(int val) { ... define it }
virtual int pop() { ... define it}
... more members
};
并以多态方式使用它:
Concept* a = new f1();
Concept* b = new f2();
// dynamic_cast<f1>(a) will return a f1*
// dynamic_cast<f2>(b) will return a f2*
我不认为您真的想要一个接口,其中包含不定数量的具有不同参数的 push 和 pop 方法。我也不认为您希望 Concept 后代有许多不同的实现,并且每种类型都有一个单独的堆栈。
看起来你想要将不同类型的对象压入堆栈然后弹出它们。在这种情况下,它可能是这样的:
struct Container
{
template<typename T>
Container(T t);
template<typename U>
U cast();
};
class Stack
{
public:
virtual void push(Container val) = 0;
virtual Container pop() = 0;
};
class ConcreteStack : public Stack
{
public:
void push(Container val);
Container pop();
};
int main()
{
ConcreteStack stack;
stack.push(25);
stack.push(std::string("abcd"));
std::string str = stack.pop().cast<std::string>();
int num = stack.pop().cast<int>();
}
不幸的是,我没有看到在 pop 时逃避显式类型转换的方法。只有返回类型不同的同名方法不在少数。
我正在通过尝试为 STL 容器实现一个类型擦除模式来练习类型擦除模式,但我坚持使用这些容器的纯虚拟成员函数。我不知道如何实现作为接口的类型擦除模式的 "concept",保存被擦除类型共享的纯虚拟成员函数。像 Push 这样的函数需要一个编译时已知的参数。据我了解,虚函数不能使用auto或模板化,那么我该如何编写接口?
我试过用关键字'typename'告诉编译器稍后会给出类型,但是编译不通过
这是我目前对 'concept' 界面的了解:
class Concept{
public:
virtual void push(typename T val) = 0;
virtual typename T pop() = 0;
};
目前收到的错误是这样的:
error: expected nested-name-specifier before ‘T’ virtual void push(typename T val) = 0;
^
error: expected ‘,’ or ‘...’ before ‘val’ virtual void push(typename T val) = 0;
^~~
error: expected nested-name-specifier before ‘T’ virtual typename T pop() = 0;
如果有人能就此给我一些建议,我将不胜感激。预先感谢大家的热心帮助和宝贵时间。
typename 关键字只能是模板声明的一部分。
template <typename T> class Concept{
public:
virtual void push(T val) = 0;
virtual T pop() = 0;
};
你脑子里混合了模板和纯虚函数。第一个是编译时间,第二个是运行时间.
模板让您避免为不同的数据类型重复代码,其中纯虚拟成员函数允许您使用从同一类型继承的不同多态接口。 Type erasure 也与虚拟成员函数无关。两个完全不同的东西。
一旦上面的模板被实例化,比如说,int
,那么它就等于:
class Concept{
public:
virtual void push(int val) = 0;
virtual int pop() = 0;
};
现在这个class是抽象的;你不能实例化它,但你可以继承:
class f1 : public Concept {
public:
virtual void push(int val) { ... define it }
virtual int pop() { ... define it}
};
class f2 : public Concept {
public:
virtual void push(int val) { ... define it }
virtual int pop() { ... define it}
... more members
};
并以多态方式使用它:
Concept* a = new f1();
Concept* b = new f2();
// dynamic_cast<f1>(a) will return a f1*
// dynamic_cast<f2>(b) will return a f2*
我不认为您真的想要一个接口,其中包含不定数量的具有不同参数的 push 和 pop 方法。我也不认为您希望 Concept 后代有许多不同的实现,并且每种类型都有一个单独的堆栈。 看起来你想要将不同类型的对象压入堆栈然后弹出它们。在这种情况下,它可能是这样的:
struct Container
{
template<typename T>
Container(T t);
template<typename U>
U cast();
};
class Stack
{
public:
virtual void push(Container val) = 0;
virtual Container pop() = 0;
};
class ConcreteStack : public Stack
{
public:
void push(Container val);
Container pop();
};
int main()
{
ConcreteStack stack;
stack.push(25);
stack.push(std::string("abcd"));
std::string str = stack.pop().cast<std::string>();
int num = stack.pop().cast<int>();
}
不幸的是,我没有看到在 pop 时逃避显式类型转换的方法。只有返回类型不同的同名方法不在少数。