2009-12-03 67 views
1

我想添加一个函数模板,如果它包含精度值或阀门和值,将打印。程序的其余部分工作,除了这个功能。我不知道我在做什么错,但我收到的错误是:模板C++错误:无法推断模板参数

错误C2784:'void printInstrumentDetail(const I * const)':无法推导出'const I * const'的模板参数从'std: :矢量< _Ty>”

#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(); 
} 
+0

我认为你的问题是你传递一个普通的对象到一个函数,该函数需要一个const指针指向一个const对象。 – 2009-12-03 16:26:07

+1

为什么'printInstrumentDetail'完全是一个模板函数?为什么不'void printInstrumentDetail(const vector &instruments);' – luke 2009-12-03 16:26:56

回答

1

传递指针到矢量

printInstrumentDetail(&band); 

和内部printInstrumentDetail

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

如果这样做,operator []将无法按预期工作。您正在取消引用矢量[] *。这会给你下一个向量,而不是向量中的下一个元素。 – 2009-12-03 16:29:12

+0

我得到它与此工作,但我的另一个问题是: a [i] - > print();包括在我的结论中......当我尝试你的决议时,发现了这一点。感谢所有帮助过的人! – lilnan 2009-12-03 16:45:37

+0

为什么不通过引用而不是指针传递向量? – 2009-12-03 17:18:14

0

嗯,首先我不相信你可以在

printInstrumentDetail(带)传递一个向量作为一个const * I const的;

5

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

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) 

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

+0

或者:修改它只取一个值,并将它与'std :: for_each'一起使用。 – 2009-12-03 16:28:38

+0

现在,我得到错误: 错误C2679:二进制“<<”:没有操作员发现这需要类型的右手操作数“无效”(或没有可接受的转换) 我改成了: 模板 \t \t \t \t \t \t \t \t // <---问题 空隙printInstrumentDetail(常量I&一个) { \t \t为(我的size_t = 0; I <6;我++) \t { \t \t cout <<的详细信息“<< a[i]-> getName() \t \t \t <<”:“<< a[i]-> print(); \t} } 并且调用它相同: printInstrumentDetail(band); 我是否需要和超载运算器来修复错误? – lilnan 2009-12-03 16:32:01

+0

哎呀抱歉关于messeged了消息 – lilnan 2009-12-03 16:32:44

0

向量不能只被转换为指针。一个工作的解决办法是这样的:


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算法等

0

您正在试图将对象传递给想要一个指针的接口。

void printInstrumentDetail(const I * const a) 

将其转换为参考。

void printInstrumentDetail(I const I& a) 

但符合在C++中常见的模式。您应该将序列的开始和结束作为参数传递。即改变你的功能,而不是一个指针迭代器。

0

不是传递指针:

printInstrumentDetail(const I * const a) 

可以通过参考:

printInstrumentDetail(const I& a) 

其他一切保持不变。

0

首先,似乎没有理由让PrintInstrumentDetail成为一个模板 - 它适用于指向基类的指针,除非您可能还有其他类型的成员,其中getName()print()成员它可能会被应用,它可以/可以/仅应用于指向基类的指针。

其次,我会考虑改变你的工作方式。我不想在每个乐器中使用成员函数,而使用PrintInstrumentDetail来遍历所有乐器,我想为仪器定义operator<<并使用标准算法打印出详细信息。

看着它,我认为还应该改变其他一些东西。首先,除非你处理非常不寻常的乐器,否则铜管乐器上的阀门数量将永远保持不变 - 因此它不应该有SetValve()成员。相反,阀门的数量应该在施工期间设定,但不能随后改变。

弦乐器根本没有阀门(至少大多数正常阀门都没有),所以他们不应该有SetValves(),GetValves()或其他与阀门有关的东西。同样,除非你做的事很不寻常,仪器的成本永远不会改变 - 你支付了你所支付的费用,所以费用应该在施工期间设定,并且不允许以后修改。

编辑:另一件事:与其在所有地方硬编码6,使用band.size()来循环乐队中的所有乐器。

+0

它的任务。教师要求我们有设置并获取每个数据成员的使用模板函数。至于具有阀门的字符串?我刚刚离开她给我们的样品输出,她的样品有“小提琴的细节有3个阀门,Cello的细节有3个阀门,等等......”我只需要得到相同的输出。 – lilnan 2009-12-03 17:18:54

+0

但是,感谢您的宝贵信息。我知道许多作业都不是高效的编码,而且很高兴知道现实世界中的代码。我认为,对这些任务中的一些任务的鄙视只是为了看看我们是否对某项具体任务有了认识,即使是a。不安。 再次感谢! – lilnan 2009-12-03 17:19:26