【问题标题】:C++: How to restrict a class template, to a class derived from a pure virtual baseC ++:如何将类模板限制为从纯虚拟基派生的类
【发布时间】:2015-03-31 10:06:20
【问题描述】:

我想在模板类上调用一个方法,我需要一种方法来确保该方法在我的模板类上。

我知道如何确保方法在类上可用的唯一方法是从纯虚拟基类派生该类。这会产生大量开销,如下面的代码所示。

显然,接口是无关紧要的,与模板类的显式特化无关,这实际上是在驱动main.cpp 中的代码。我只是过时并坚持“接口”,还是有一种现代的面向对象的方法来确保模板类是完整的?

编辑: 为了深入了解下面的代码...

有一个接口,叫做“接口”,它有一个虚析构函数和一个叫做sayHi()的纯虚方法。 A 继承自 Interface 并实现 sayHi()。然后将A 作为模板传递给Template,然后在其salutations() 方法中调用sayHi()。为了进一步混淆事情,静态方法是解决我的问题的最佳方法。但是,为了使用基类作为接口来为我的模板类提供继承,我无法使用静态方法,因此您会看到两种非静态方法来满足虚拟方法和一种静态方法来满足我的需求。

在我看来,除了以面向对象的方式组织之外,不需要接口,这会带来相当大的痛苦。是否有另一种方法来获得界面提供的秩序感,或者这种思维方式已经过时了?


main.cpp

#include "a.h"
#include "template.h"

int main (int argc, char * argv[]) {
    Template<A> a;

    a.salutations();

    return 0;
}

interface.h

#ifndef INTERFACE_H
#define INTERFACE_H

struct Interface {
    virtual
    ~Interface (
        void
    ) {}

    virtual
    void
    sayHi (
        void
    ) const = 0;
};

#endif

a.h

#ifndef A_H
#define A_H

#include "interface.h"

class A : public Interface {
  public:
    A (
        void
    );

    ~A (
        void
    );

    void
    sayHi (
        void
    ) const;

    static
    void
    sayHi (
        bool = false
    );
};

#endif

a.cpp

#include "a.h"

#include <iostream>

A::A (
    void
) {}

A::~A (
    void
) {}

void
A::sayHi (
    void
) const {
    return A::sayHi(true);
}

void
A::sayHi (
    bool
) {
    std::cout << "Hi from A!" << std::endl;
}

模板.h

#ifndef TEMPLATE_H
#define TEMPLATE_H

template <class Interface>
class Template {
  public:
    void salutations (void);
};

#endif

模板.cpp

#include "template.h"

#include "a.h"

template<>
void
Template<A>::salutations (
    void
) {
    A::sayHi();
    return;
}

【问题讨论】:

  • 我不明白你在问什么,但是除非你在调用该函数的所有翻译单元中 #include &lt;template.cpp&gt;,否则不会找到 Template&lt;A&gt;::salutations 的专业化。看到这个解释 - stackoverflow.com/q/495021/241631
  • @Praetorian 从您链接的帖子中:“问题不正确。还有另一种可移植方式。模板类可以显式实例化 - 正如其他答案所指出的那样。 – Aaron McDaid 2012 年 8 月 27 日 11:42”。这正是我在上面的示例代码中说明的内容。
  • 根本不清楚您要做什么。请显示您想要工作的代码。
  • @n.m.接口,字面意思是“接口”,有一个虚析构函数和一个纯虚方法sayHi()A 继承自 Interface 并实现 sayHi()。然后将A 作为模板传递给Template,然后在其salutations() 方法中调用sayHi()。除了以面向对象的方式组织之外,不需要接口。
  • 模板没有调用虚函数,因为它没有A类型的对象,所以不能这样做。它调用了一个完全不相关的静态函数。该接口没有任何作用。任何与Interface 无关的类都可以愉快地定义sayHi 并成功地用作Template 的模板参数。确实从 Interface 派生但未定义任何静态函数的类不能。

标签: c++ templates inheritance


【解决方案1】:

C++ 不是 Java。我不知道如何说类或类型名必须从另一个类派生。

真的是duck typing。只需使用这些方法,如果它们不存在,编译器就会抛出错误。顺便说一句,当你写

template <class Interface>
class Template {
  public:
    void salutations (void);
};

Interface 在这里与T 相同:它不需要使用的特化是class Interface 的子类。

【讨论】:

  • 您可以使用std::enable_if&lt;std::is_base_of&lt;Interface, T&gt;::value&gt;::type,但这并没有多大意义。如果我们已经在使用动态多态性,为什么还要使用模板?
  • @5gon12eder 我对使用接口不感兴趣。多态性与硬件相关,将在编译时完成。您可以在答案中扩展 std::enable_if... 吗?
  • @Zak 那么你的问题很有误导性,因为你的代码到处都在使用virtual
  • @5gon12eder 我尽可能少地使用virtual,以便编译代码。重点是使用接口来确保方法可用,我正在寻找更好的解决方案。
  • @Zak 不,因为我懒得弄清楚你到底在问什么;-)
猜你喜欢
  • 2013-10-07
  • 1970-01-01
  • 2018-01-25
  • 1970-01-01
  • 2015-07-12
  • 2021-03-19
  • 2011-03-20
  • 1970-01-01
相关资源
最近更新 更多