【问题标题】:Templates C++ error : could not deduce template argument模板 C++ 错误:无法推断模板参数
【发布时间】:2010-12-22 21:32:24
【问题描述】:

我正在尝试添加一个函数模板,如果它包含精度值或阀门和值,它将打印。除此功能外,该程序的其余部分均有效。我不确定我做错了什么,但我收到的错误是:

错误 C2784:“void printInstrumentDetail(const I *const)”:无法从“std::vector<_ty>”推导出“const I *const”的模板参数

#include <iostream>
#include <vector>
#include <iomanip>
#include <string>
#include "Instruments.h"
#include "Brass.h"
#include "Strings.h"

using namespace std;

//template<typename I>                    <---Problem
//void printInstrumentDetail(const I * const a)
//{
//      for (size_t i = 0; i < 6; i ++)
//  {
//      cout << "The details for " << a[i]->getName()
//          << ": " << a[i]->print();
//  }
//}
int main()
{
    double total = 0;

    Strings violin("Violin", 553.90, 3);
    Strings cello("Cello", 876.45, 3);
    Strings viola("Viola", 200.50, 23);
    Brass tuba("Tuba", 1400.10, 1.23);
    Brass trumpet("Trumpet", 500.00, 4.32);
    Brass sax("Sax", 674.78, .99);

    vector <Instruments *> band(6);

    band[0] = &violin;
    band[1] = &tuba;
    band[2] = &cello;
    band[3] = &trumpet;
    band[4] = &viola;
    band[5] = &sax;

    cout << fixed << setprecision(2);

    cout << "The instruments in the band are:\n";
    //Get name and cost of each
    for (size_t i = 0; i < 6; i ++)
    {
        cout << band[i]->getName() << "     $" 
            << band[i]->getCost() << endl;
    }

    cout << "\nThen band is warming up..." << endl;
    //Get descrition of how sound is made of each
    for (size_t i = 0; i < 6; i ++)
    {
        cout << "This " << band[i]->getName()
            << " makes sounds by " ;
        band[i]->playSound();
    }
    cout << "\nTotal cost of the band is: $" ;
    //Get total cost of all instruments
    for (size_t i = 0; i < 6; i ++)
    {

        total = band[i]->getCost() + total;
    }
    cout << total << endl;

    //printInstrumentDetail(band);                     <--Problem

    return 0;
}

这是基类:

#ifndef INSTRUMENTS_H
#define INSTRUMENTS_H

#include <string>

using namespace std;

class Instruments
{
public:
    Instruments(string, double);

    void setName(string);
    virtual string getName();

    void setCost(double);
    virtual double getCost();

    virtual void print();

    virtual void playSound();

private:
    string name;
    double cost;
};
#endif

#include <iostream>
#include "Instruments.h"

using namespace std;

Instruments::Instruments(string n, double c)
{
    name = n;
    cost = c;
}
void Instruments::setName(string n)
{
    name = n;
}
string Instruments::getName()
{
    return name;
}
void Instruments::setCost(double c)
{
    cost = c;
}
double Instruments::getCost()
{
    return cost;
}
void Instruments::print() 
{

}
void Instruments::playSound()
{
    //empty
}

派生类低音:

#ifndef BRASS_H
#define BRASS_H

#include <string>
#include "Instruments.h"

using namespace std;

class Brass : public Instruments
{
public:
    Brass(string, double, double);

    void setPrecisionValue(double);
    double getPrecisionValue();
    void print() ;
     void playSound();

private:
    double precision;
    string sound;
};
#endif

#include <iostream>
#include "Brass.h"

using namespace std;

Brass::Brass(string n, double c, double p)
:Instruments(n, c)
{
    precision = p;
}
void Brass::setPrecisionValue(double p)
{
    precision = p;
}
double Brass::getPrecisionValue()
{
    return precision;
}
void Brass::print() 
{
    cout << getPrecisionValue() << endl;
}
void Brass::playSound()
{
    cout << "blowing in a mouthpiece." << endl;
    Instruments::playSound();
}

派生类字符串:

#ifndef STRINGS_H
#define STRINGS_H

#include <string>
#include "Instruments.h"

using namespace std;

class Strings : public Instruments
{
public:
    Strings(string, double, int);

    void setValves(int);
    int getValves();
    void print();
    void playSound();

private:
    int valves;
};
#endif

#include <iostream>
#include "Strings.h"

using namespace std;

Strings::Strings(string n, double c, int v)
    :Instruments(n, c)
{
    valves = v; 
}
void Strings::setValves(int v)
{
    valves = v;
}
int Strings::getValves()
{
    return valves;
}
void Strings::print() 
{
    cout<< getValves() << endl;
}
void Strings::playSound()
{
    cout << "striking with a bow." << endl;
    Instruments::playSound();
}

【问题讨论】:

  • 我认为你的问题是你将一个普通对象传递给一个函数,该函数需要一个指向 const 对象的 const 指针。
  • 为什么printInstrumentDetail 完全是一个模板函数?为什么不void printInstrumentDetail(const vector&lt;Instrument*&gt;&amp; instruments);

标签: c++


【解决方案1】:

好吧,首先我不相信你可以将向量作为 const * I const at 传递

printInstrumentDetail(band);

【讨论】:

    【解决方案2】:

    将指针传递给向量

    printInstrumentDetail(&band);   
    

    printInstrumentDetail内部

    (*a)[i]->getName();
    

    【讨论】:

    • 如果你这样做, operator[] 将无法按预期工作。您正在取消引用向量[]*。这将为您提供下一个向量,而不是向量中的下一个元素。
    • 我让它可以解决这个问题,但我的另一个问题是:a[i]->print();包括在我的 cout 中......当我尝试你的解决方案时,我发现了这一点。非常感谢所有帮助过的人!
    • 事实上,如果我想要更好的解决方案,我会选择一对迭代器。
    【解决方案3】:

    嗯,问题是你的模板需要一个指针:

    template<typename I>   
    void printInstrumentDetail(const I * const a);
    

    但你给它的是一个向量,而不是一个指针:

    vector <Instruments *> band(6);
    ...
    printInstrumentDetail(band);
    

    您可以通过将指针传递给printInstrumentDetail 函数来解决这个问题,如下所示:

    printInstrumentDetail(&band[0]);
    

    但实际上,您最好修改 printInstrumentDetail 以获取一个容器或一对迭代器:

    template <typename ContainerT>   
    void printInstrumentDetail(const ContainerT& a)
    

    template <typename IteratorT>
    void printInstrumentDetail(IteratorT first, IteratorT last)
    

    对函数的定义进行适当的修改。

    【讨论】:

    • 或者:修改为只取一个值,和std::for_each一起使用。
    • 现在我收到错误:错误 C2679: 二进制 ' //getName() print();并用相同的方法调用它: printInstrumentDetail(band);我需要重载运算符来修复错误吗?
    • 抱歉消息混乱
    【解决方案4】:

    Vector 不能只转换为指针。一种可行的解决方案是:

    
    template <typename T>
    void printInstrumentDetail( const std::vector<T*>& band )
    {
        for ( size_t i = 0; i < band.size(); ++i )
            cout << "The details for " << band[i]->getName()
                 << ": " << band[i]->print();
    }
    

    还有很多其他的,包括迭代器、函子、STL 算法等。

    【讨论】:

      【解决方案5】:

      您正在尝试将对象传递给需要指针的接口。

      void printInstrumentDetail(const I * const a)
      

      将此转换为参考。

      void printInstrumentDetail(I const I& a)
      

      但要符合 C++ 中常见的模式。您应该将序列的开头和结尾作为参数传递。即更改您的函数以采用迭代器而不是指针。

      【讨论】:

        【解决方案6】:

        而不是传递指针:

        printInstrumentDetail(const I * const a)  
        

        你可以通过参考:

        printInstrumentDetail(const I& a)
        

        其他一切都保持不变。

        【讨论】:

          【解决方案7】:

          首先,PrintInstrumentDetail 似乎根本没有理由成为模板——它适用于指向基类的指针,除非您可能有其他类型的 getName()print()可能应用它的成员,它可以/可以/应该只使用指向基类的指针。

          其次,我会认真考虑改变你的工作方式。而不是每个 Instrument 中的成员函数,以及 PrintInstrumentDetail 循环遍历所有工具,我会认真考虑为 Instrument 定义 operator&lt;&lt;,并使用标准算法打印出详细信息。

          看着它,我认为其他一些事情也应该改变。首先,除非你正在处理非常不寻常的乐器,否则铜管乐器上的阀门数量是永远固定的——所以它不应该有SetValve() 成员。相反,阀门的数量应该在施工时设定,而不是开放后改变。

          弦乐器根本没有阀门(至少大多数普通乐器没有),所以它们不应该有 SetValves()GetValves() 或任何与阀门相关的东西。

          同样,除非您在做一些非常不寻常的事情,否则仪器的成本永远不会改变 - 您支付了您所支付的费用,因此应该在施工期间确定成本,而不是以后更改。

          编辑:另一件事:不要到处硬编码6,而是使用band.size() 循环遍历乐队中的所有乐器。

          【讨论】:

          • 这是一个任务。讲师要求我们为每个数据成员设置和获取,使用模板函数。至于带阀门的弦乐???我刚刚离开了她给我们的样本输出,她的样本有“小提琴的细节有 3 个阀门。大提琴的细节有 3 个阀门。等等......”我只需要获得相同的输出。跨度>
          • 感谢您提供宝贵的信息。我确实知道许多作业都不是有效的编码,很高兴知道现实世界中的代码是什么。我认为对其中一些任务的认可只是为了看看我们是否对特定任务有了解,即使是认可的。再次感谢!!
          猜你喜欢
          • 1970-01-01
          • 1970-01-01
          • 2012-11-14
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 2013-12-09
          • 2013-02-18
          相关资源
          最近更新 更多