2009-12-03 65 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