【发布时间】:2014-08-17 16:34:48
【问题描述】:
最近我发现了一个更容易进行模板特化而不是真正继承的情况。派生类只需要实现一个纯虚函数并且没有自己的成员。是这样的:
#include <iostream>
class Interface {
public:
virtual void calculate() = 0;
virtual float getResult() = 0;
};
class Base : public Interface {
float result;
public:
Base() : result(1) {};
virtual ~Base() {};
virtual void calculate();
virtual float getValue() = 0; // do some very complex calculation here
float getResult() { return result; }
};
class DerivedA : public Base {
public:
DerivedA() : Base() {};
~DerivedA() {};
float getValue();
};
class DerivedB : public Base {
public:
DerivedB() : Base() {};
~DerivedB() {};
float getValue();
};
void Base::calculate() {
for (int i = 0; i < 10; i++)
result += getValue();
}
float DerivedA::getValue() {
return 1;
}
float DerivedB::getValue() {
return 1.1;
}
int main() {
Interface * a = new DerivedA();
a->calculate();
Interface * b = new DerivedB();
b->calculate();
std::cout << "Result A: " << a->getResult() << std::endl;
std::cout << "Result B: " << b->getResult() << std::endl;
delete a;
delete b;
}
这可以写成专门的模板:
#include <iostream>
class Interface {
public:
virtual void calculate() = 0;
virtual float getResult() = 0;
};
template<typename T>
class Base : public Interface {
float result;
public:
Base() : result(1) {};
void calculate();
float getValue(); // do some very complex calculation here
float getResult() { return result; };
};
typedef Base<int> DerivedA; // actually int and float are only examples
typedef Base<float> DerivedB; // and may be some much more complex types!
template<typename T>
void Base<T>::calculate() {
for (int i = 0; i < 10; i++)
result += getValue();
}
template<typename T>
float Base<T>::getValue() {
return 0;
}
template<>
float Base<int>::getValue() {
return 1;
}
template<>
float Base<float>::getValue() {
return 1.1;
}
int main() {
Interface * a = new DerivedA();
a->calculate();
Interface * b = new DerivedB();
b->calculate();
std::cout << "Result A: " << a->getResult() << std::endl;
std::cout << "Result B: " << b->getResult() << std::endl;
delete a;
delete b;
}
两个示例给出相同的结果,我猜第二个更快,因为不需要评估虚拟表(getValue() 方法甚至可以在第二种情况下内联)。
所以我的问题是:使用模板专业化而不是继承有什么限制?有没有我没见过的副作用?继承比模板专业化有什么好处?我知道我不能像为派生类创建新成员和方法那样为专门的类创建新成员和方法。但是对于我只需要实现一些特定于类型的代码的用例来说,这是否可以是一种通用的、性能更高的方法?
顺便说一句:这种模式有名字吗?
【问题讨论】:
-
如果你以后需要
DerviedC,而getValue应该返回4.2,你会怎么做?完全不清楚练习的目的是什么。据我所知,整个 shebang 可以用一个独立的函数float calculate(float)替换。 -
本例中用于模板特化的类型只是示例。就我而言,我还有一些其他类型。更准确地说:我必须序列化更复杂类型的列表。但是 getValue() 的作用在这里并不重要。无论如何,这将是两种方法之间的共同部分。
-
如所写,我不明白您要做什么。你的例子对我来说没有多大意义。也许你可以想出一个更现实的场景,其中所有这些扭曲都是真正需要的。
-
你在找CRTP吗?
标签: c++ templates inheritance