由于无法解析模板参数而导致多态失败?

时间:2016-07-13 20:24:03

标签: c++ templates inheritance

我知道这似乎很复杂,但我希望有人可以在这里指出我的错误。我确信这个设计会让你的嘴巴有些不好,我很高兴听到设计方案。但表格来自问题领域的建模。

我确定我很傻,但是模板与继承相结合的方式让我很困惑。以下是一些简化代码,其中包含以下说明:

// main.cpp

#include <cstdio>

template <typename POD>
class A {
 public:
  POD data;
  POD get_a() { return data; }
};

template <typename T>
class B {
 public:
  virtual void do_something_with_an_A_child(const T&) = 0;
};

class ADerived : public A<float> {
 public:
  ADerived(float a) { data = a; }
};

class BDerived : public B<ADerived> {
 public:
  virtual void do_something_with_an_A_child(const ADerived& someA) {
    printf("A bit of A-type's data: %f\n", someA.data);
  }
};

template <typename POD>
class Aggregator {
 public:
  A<POD>* instanceOfA;
  B<A<POD>>* instanceOfB;
  Aggregator(A<POD>* anA, B<A<POD>>* aB) : instanceOfA(anA), instanceOfB(aB) {}
};

int main() {
  ADerived myADerived(3.14159f);
  BDerived myBDerived;

  Aggregator<float> myAggregator(&myADerived, &myBDerived);

  return 1;
}

所以A是一个类模板,其签名只是一些内置类型。 (在我的特定情况下,A具有对其内部数据进行操作的方法。)类B旨在承诺某些操作的接口,这些操作适用于{{1}的特定实例}。因此,在上面的代码中,您看到我将A<.>A定义为模板类,然后创建继承自这些模板类的类,并提供BADerived。< / p>

(在实际情况中,BDerived表示数学模型和一些数据,A是用于对模型执行数学优化的接口。)

现在,一个应该链接到BADerivded实例的类(为了创建基于其接口的通用算法)我调用了BDerived,只需在构造函数中获取一些指针。我只希望Aggregator需要知道Aggregator类型,因为它只是为了操纵接口而不是太担心对象包含的内容。

我从POD clang++收到以下编译错误:

-std=c++14

含义很明确,但我不确定为什么它看不到main.cpp:42:21: error: no matching constructor for initialization of 'Aggregator<float>' Aggregator<float> myAggregator(&myADerived, &myBDerived); ^ ~~~~~~~~~~~~~~~~~~~~~~~~ main.cpp:35:3: note: candidate constructor not viable: no known conversion from 'BDerived *' to 'B<A<float> > *' for 2nd argument Aggregator(A<POD>* anA, B<A<POD>>* aB) : instanceOfA(anA), instanceOfB(aB) {} ^ BDerived。我的意思是,它具体是B<A<float>>,但B<ADerived>ADerived,因此A<float>应该被视为BDerived。这显然不是这样,所以要么我做了一些愚蠢的事情,希望有人指出它,或者这在C ++中是不可能的,我需要一些替代的设计建议。

1 个答案:

答案 0 :(得分:2)

模板参数以静态方式和精确类型解析。因此即使B<ADerived>B<A<POD>>的后代,ADerived也不会衰减到A<POD>。您可以通过以下方式解决此问题:

  • T中再添加一个模板参数Aggregator,并可选择确保{使用std::enable_if<>std::is_base<>A<POD>T的基础{1}}或
  • 使用TB中公开typedef,然后在T中取Aggregator并将TA<B::T>存储在Aggregatorpublic class Print2ndChar { public static void main(String[] args) throws java.lang.Exception { Print2ndChar mainObj = new Print2ndChar(); java.io.BufferedReader inputReader = new java.io.BufferedReader(new java.io.InputStreamReader(System.in)); String noOfTestCase; if(((noOfTestCase = inputReader.readLine()) == null)) System.exit(0); int noOfLines = 0; try{ noOfLines = Integer.parseInt(noOfTestCase); }catch(Exception e){ System.exit(0); } if(noOfLines<0 || noOfLines>100) System.exit(0); String [] randomWords = new String[noOfLines]; for(int i=0;i<noOfLines;i++){ randomWords[i] = inputReader.readLine(); if(randomWords[i] == null || randomWords[i].length()<2 || randomWords[i].length()%2!=0 || (randomWords[i].length()/2)>100) System.exit(0); } for (String word : randomWords){ mainObj.letsBegin(word.substring(0, word.length() / 2)); System.out.println(); } } private void letsBegin(String data) { if (data.length() <= 0) { return; } else { System.out.print(data.charAt(0)); if (data.length() >= 3) letsBegin(data.substring(2, data.length())); } } }