【发布时间】:2014-12-31 21:33:07
【问题描述】:
我有一个模板和许多派生类。在所有这些类中,我想使用模板类型和它的一些依赖类型(实际上我有很多类型和许多依赖类型)。
以下方法很糟糕,因为我需要手动继承(使用关键字)父类的所有类型(参见代码示例):
编辑:我不知道我想使用类型的类也是一个模板很重要。我相应地更新了代码示例。
template<class T>
class A {
using TBase = T;
using TDerived = T[10];
}
template<class T>
class B : A<T> {
// NOTE i want the types TBase and TDerived here and in further children
using TBase = A<T>::TBase;
using TDerived = A<T>::TDerived
}
class C : B<int> {
// NOTE i want the types TBase and TDerived here and in further children
using TBase = B<int>::TBase;
using TDerived = B<int>::TDerived
}
我还考虑了模板化命名空间,以便我可以在类之外定义类型 - 但它们不存在。
有人有更好的主意吗?
解决方案 1:修复当前方法
(基于 Jan Hudec 的 cmets 和 Oguk 的答案)
-
公共继承
我忘记了类的关键字public:(结构默认是公共的)。 -
缺少
typename
在误导性的类中使用我的(错误)类型的编译器警告(尽管using关键字的那些直接暗示缺少typename keyword)。
关于何时使用typename的更多说明可以在这里找到:https://stackoverflow.com/a/7923419/3779655 -
类型交互
当我正确指定类型时(例如,参见 2.missingtypename),我也可以使用当前的类名。
结果代码:
template<class T>
class A {
public:
using TBase = T;
using TDerived = T[10];
};
template<class T>
class B : public A<T> {
public:
// possiblity 1:
using TBase = typename B::TBase;
TBase memberB1;
// possibility 2
typename B::TBase memberB2;
};
class C : public B<int> {
public:
// NOTE C is no template -> we don't have to do anything
TBase memberC;
};
解决方案2:特征类
(基于Oguk的回答)
-
使用模板化特征类而不是命名空间
这提供了几乎相同的功能。 -
类型信息的不同可用性
我以前没有想到的一件事是检查哪些类型信息在哪里可用,以及是否需要更多字符才能从父类中检索所需的类型信息(请参阅 NOTE cmets)。
见下面的代码:
template<class T>
struct TypesContainer {
using TBase = T;
using TDerived = T[10];
};
template<class T>
class A {
public:
// TODO possible to directly inherit all types?
//using TypesContainer<T>;
// NOTE this is only possible for methods, not types
using Types = TypesContainer<T>;
typename Types::TBase memberA;
};
class B : public A<int> {
public:
// NOTE here I have all template information via definition (by hand)
using Types = TypesContainer<int>;
typename Types::TBase memberB;
};
class C : public B {
public:
// NOTE here I don't have the type information any more
using Types = TypesContainer<A::Types::TBase>;
typename Types::TBase memberC;
};
问题:
有没有办法在类范围内直接继承命名空间/类的所有成员(参见 TODO 注释)。使用 using 关键字而不使用赋值运算符 = 仅适用于 methods 而不是 namespaces、classes 和 types。
【问题讨论】:
-
B 类自动继承 TBase 和 TDerived,您无需执行任何操作。但是如果你私下继承
A<int>,它们是私有的,所以后代看不到它们;你需要公开继承(如果你愿意,你也可以继承 protected,但我不确定这是否有意义)。 -
请注意,如果
B类是模板并且基类依赖于参数,则您必须限定继承的类型。但是 IIRC 用B::对它们进行限定应该可以工作。 -
@JanHudec 感谢您的回答。很抱歉我不能投票给他们,因为我没有足够的声誉:(
-
using当然应该适用于类型。 -
@JanHudec 我的意思是在没有等号的情况下使用它,就像我在解决方案2 (
using TypesContainer<T>;) 中的 TODO 评论之后一样。这样做(有或没有typename)会导致编译器错误error: expected nested-name-specifier!
标签: c++ templates inheritance using