【问题标题】:C++ template declaration with inheritance list带有继承列表的 C++ 模板声明
【发布时间】:2017-07-27 10:11:24
【问题描述】:

是否可以在 C++ 中声明一个模板类以及它所继承的类?基本上我想给编译器一个提示,我的模板类在声明时总是会继承另一个。 也许一些代码会澄清为什么这对我来说是个问题:

template<typename T>
class GrandparentClass
{
public:
    T grandparentMember;
};

//this needs to be only a declaration, since I do not want classes of ParentClass with random T
template<typename T>
class ParentClass : public GrandparentClass<T>
{

};

// this does not work:
//template<typename T>
//class ParentClass : public GrandparentClass<T>;

// this does not either, because then the child class cannot access the variable from the grandparent class
//template<typename T>
//class ParentClass;

template<>
class ParentClass<int> : public GrandparentClass<int>
{
public:
    ParentClass()
    {
        grandparentMember = 5;
    }
};

template <typename T>
class ChildClass : public ParentClass<T>
{
public:
    void foo()
    {
        std::cout << grandparentMember << "\n";
    }
};

另外,我不能使用 C++ 11。

编辑:

我找到了一个简单的方法:

template<typename T>
class ParentClass : public GrandparentClass<T>
{
public:
    ParentClass() { ParentClass::CompilerError(); };
};

只是不要在类中定义 CompilerError() 方法,一切都很好。

【问题讨论】:

  • 是的,应该可以。您认为问题在哪里?
  • 没有。类声明取自 class foo;。无论是否模板,这都不能包含基类。即使可以,专业化仍然必须再次包含它。
  • 问题是你不能把定义改成template&lt;typename T&gt; class ParentClass : public GrandparentClass&lt;T&gt;;我在代码里编辑一下
  • 为什么要给编译器这样的提示?无论如何,编译器在知道具体的参数分配之前不会解释声明,所以它没有用这样的提示。
  • 我想禁止使用与我专门针对的类型名称不同的类型名称来实例化 ParentClass,而祖父母成员仍然应该可以从子类访问。基本上我不想为任何 T 提供 ParentClass 的定义,只是针对特定类型。

标签: c++ templates inheritance declaration c++03


【解决方案1】:

类声明只对非值变量声明有用,比如指针和引用。但是,您无法访问类成员,甚至无法实例化它。即使您知道声明的类继承自其他类,您仍然不一定能够以任何方式利用该信息。

因此,对于编译器来说,了解类的完整定义后,它才知道类继承自什么。


在 cmets 中澄清后:如果你想阻止具有某些类型的类模板的实例化,它的定义就是这样做的地方。在类体内一个简单的static_assert 就可以了; Boost.StaticAssert 或更旧的 SFINAE 技巧将完成 C++11 之前的代码的工作。

【讨论】:

  • @lightxbulb 以及您想要实现的目标是什么?
  • 禁止使用与我专门针对的类型名称不同的类型名称来实例化 ParentClass,而祖父母成员仍应可从子类访问。基本上我不想为任何 T 提供 ParentClass 的定义,只是针对特定类型。
  • 那么你可以在你的ParentClass 中添加一个static_assert 吗?
  • 我相信这是 C++ 11 的一个特性。
  • @lightxbulb, Boost.StaticAssert 是一个可以在 C++98 中正常工作的定义,除了不太明显的错误消息。根据需要将其导入或复制到您的项目中。并不复杂。
【解决方案2】:

如果您对将错误延迟到链接时间而不是编译时间感到满意,您可以在 parent.h 中声明 parent 的所有成员函数,在 parent.cpp 中提供定义,并显式实例化有限的类列表你想要的。

父.h

template<typename T>
class ParentClass : public GrandparentClass<T>
{
    ParentClass();
};

class ParentClass<int>;
class ParentClass<long int>; // or whatever

父.cpp

template <typename T>
ParentClass::ParentClass() : grandparentMember(5) {}

【讨论】:

  • 我受到了您的解决方案的启发,但将其变成了编译时错误,因为根据我的经验,它们更具可读性。
猜你喜欢
  • 1970-01-01
  • 2012-05-30
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2012-04-11
  • 2011-06-10
  • 2017-04-29
  • 1970-01-01
相关资源
最近更新 更多