我有以下基本模板类。
template<typename T>
class Base {
public:
void do_something() {
}
};
它旨在用作奇怪的重复模板模式。它应该像class B : public Base<B>
一样继承。它必须不继承,如class B : public Base<SomeoneElse>
。我想静态地执行这个要求。如果有人使用了这个错误,我预计编译阶段会出错。
我正在做的是在static_cast<T const&>(*this)
中添加do_something()
。这样,继承模板的类是继承自作为模板参数提供的类。抱歉这个令人困惑的表情。简单地说,B
需要SomeoneElse
或class B : public Base<SomeoneElse>
中的B
继承。
我不知道这是否是实现这一目标的最佳方式。看起来很粗鲁。
但是我想做更多。我想确保SomeoneElse
本身INFO [94db8027] Running /usr/bin/env uptime on leehambley@example.com:22
DEBUG [94db8027] Command: /usr/bin/env uptime
DEBUG [94db8027] 17:11:17 up 50 days, 22:31, 1 user, load average: 0.02, 0.02, 0.05
INFO [94db8027] Finished in 0.435 seconds command successful.
。我怎么能这样做?
答案 0 :(得分:8)
将Base
的构造函数(或析构函数)设为private,然后将T
设为friend
。这样,构建/破坏Base<T>
的唯一方法就是T
。
答案 1 :(得分:3)
如果您的类包含一些代码:
T* pT = 0;
Base *pB = pT;
如果T
与Base
不分配兼容,则会出现编译错误。
这种检查在C ++ 11中已经形式化,因此您不必手动编写它并且可以获得有用的错误消息:
#include <type_traits>
template<typename T>
class Base {
public:
void do_something()
{
static_assert(
std::is_base_of<Base, T>::value,
"T must be derived from Base");
}
};
class B : public Base<B> { };
int main()
{
B b;
b.do_something();
}
至于确保Base
的类型参数正是从它派生的类,这看起来在概念上是有缺陷的。充当基类的类不能“谈论”继承它的类型。它可以通过多重继承而不是一次继承,或者根本不继承。
答案 2 :(得分:1)
到目前为止有两个好的答案。这是另一个使用为某些方法生成自定义访问键的习语(在这种情况下是构造函数)。它提供了正确使用的绝对保证,同时不将基础中的私有方法暴露给派生。
它还可以用于根据具体情况控制对基类中其他方法的访问。
template<class Derived>
struct Base
{
private:
// make constructor private
Base() = default;
protected:
// This key is protected - so visible only to derived classes
class creation_key{
// declare as friend to the derived class
friend Derived;
// make constructor private - only the Derived may create a key
creation_key() = default;
};
// allow derived class to construct me with a key
Base(creation_key)
{}
// other methods available to the derived class go here
private:
// the rest of this class is private, even to the derived class
// (good encapsulation)
};
struct D1 : Base<D1>
{
// provide the key
D1()
: Base<D1>(creation_key())
{}
};