2012-02-18 68 views
0

模板我有是:錯誤而

template <class T> 
class Shape { 
T val,val_new; 
public: 
Shape(T initval) 
{ 
    val=initval; 
} 
T get() 
{ 
    return val; 
} 
void set (T newval) 
{ 
    val_new = newval; 
} 
void copy() 
{ 
    val= val_new; 
} 
}; 

使用此模板的類是:

#include <iostream> 
#include<math.h> 
using namespace std; 
class Rectangle 
{ 
private: 
Shape<TwoPoint> val; 
bool incr_called, decr_called, load_called; 
TwoPoint newval; 
public: 
Rectangle(TwoPoint i) 
     : val (Shape<TwoPoint> (i)) {}  
Shape<TwoPoint> read() 
{ 
    return val; 
} 
void load(TwoPoint n) 
{ 
    load_called=1; 
    newval=n; 
} 
void increment() 
{ 
    incr_called=1; 
} 
void decrement() 
{ 
    decr_called=1; 
} 
void init() 
{ 
    incr_called=0; 
    decr_called=0; 
    load_called=0; 
} 
void actions() 
{ 
    if (load_called) 
     val.set(new TwoPoint(newval)); 
    if(incr_called && !decr_called) 
     val.set((new TwoPoint(val.get())).plus(1)); 
    if(!incr_called && decr_called) 
     val.set((new TwoPoint(val.get())).plus(-1)); 
}  
}; 

的兩點類被定義爲:

class TwoPoint 
{ 
    int width; 
    int value; 
    public: 
    TwoPoint() 
    { 
     value=0; 
     width=0; 
    } 
    TwoPoint(int v, int w) 
    { 
     value=v; 
     width=w; 
    } 
    TwoPoint(const TwoPoint& t) 
    { 
     value= t.value; 
     width= t.width; 
    } 
    int getWidth() 
    { 
     return width; 
    } 
    int getValue() 
    { 
     return value; 
    } 
    TwoPoint & plus(int newval) 
    { 
     value+=newval; 
     return *this; 
    } 
    }; 

但有錯誤:

In member function 'void Rectangle::actions()': 
error: request for member 'plus' in '(((TwoPoint*)operator new(8u)), (((*<anonymous>) 
<unknown operator> TwoPoint<T>::get() [with T=TwoPoint]()), <anonymous>))', which is of non-class type 'TwoPoint*' 

還有另一個錯誤:

In member function 'void Rectangle::actions()': 
error: no pattern matching function for call to 'Shape<TwoPoint>::set(TwoPoint*)' 
note: candidates are: void Shape<T>:: set<T> [with T=TwoPoint] 

有兩個錯誤,當我在行動做類似的操作(),由於同樣的原因。有人可以解釋這些錯誤以及如何改進它們嗎? 有什麼辦法可以讓代碼更高效?

回答

2

Shape::set按值取其參數,但是您使用new並傳遞指針創建一個值。除非實際需要動態對象,否則應該避免使用new;在這種情況下,您需要確保在完成操作後將其刪除。

在這種情況下,你只是想通過值傳遞的對象:

void actions() 
{ 
    if (load_called) 
     val.set(newval); 
    if(incr_called && !decr_called) 
     val.set(val.get().plus(1)); 
    if(!incr_called && decr_called) 
     val.set(val.get().plus(-1)); 
}  

Is there any way in which i can make code more efficient?

動態分配通常比使用自動對象效率較低 - 固定誤差也除去效率低下的一個來源。

Shape::set和構造,可以參照拿自己的論點,並Shape::get可以返回一個參考,以避免不必要的複製;儘管實際上編譯器可能會無視這些副本。此外,構造函數可以使用初始化列表來直接初始化成員,而不是默認初始化它們並重新分配它們。像這樣的代碼可能會在某些情況下會稍微更高效:

Shape(T const & initval)  // pass by reference 
    : val(initval)    // use initialiser list 
{} 
T const & get()    // return by reference 
{ 
    return val; 
} 
void set (T const & newval) // pass by reference 
{ 
    val_new = newval; 
} 

但在一般情況下,專注於使代碼正確和可讀性,並選擇有效的算法;如果他們證明是一個瓶頸,只擔心小的低效率。

1

你有這樣的:

(new TwoPoint(val.get())).plus(1) 

new返回一個指針-TO-TwoPoint,所以你必須使用->,而不是.訪問成員函數。

但是,如果你這樣做,你會得到一般情況下的內存泄漏。我會建議重新考慮你的設計,這樣你就不需要動態分配東西。

+0

能否請您解釋一下 – 2012-02-18 11:48:44

+0

@user:說明哪個部分? – 2012-02-18 11:49:02

+0

我不明白內存泄漏部分 – 2012-02-18 11:51:13

2

運營商new是那裏的明顯罪魁禍首。使用自動變量解決內存泄漏問題。當像Shape和TwoPoint這樣的類可以作爲參考而不是被複制的值傳遞時,代碼會得到進一步改進。我承認對你的代碼感到有些無聊和煩躁,甚至用ostream添加調試輸出。儘管如此,我無法幫助您理解應用程序的邏輯。我不知道爲什麼某些結構在那裏,所以我保持其中大部分完整(val_new除外,因爲目前它沒有添加任何代碼)。

#include <iostream> 
#include <math.h> 
using namespace std; 

class TwoPoint { 
    int value, width; 
public: 
    TwoPoint() : value(0), width(0) {} 
    TwoPoint(int v, int w) : value(v), width(w) {} 
    TwoPoint(const TwoPoint& t) : value(t.value), width(t.width) {} 
    int getWidth() { return width; } 
    int getValue() { return value; } 
    TwoPoint & plus(int newval) { value += newval; return *this; } 
    friend ostream& operator<< (ostream& os, const TwoPoint& x); 
}; 

template <class T> class Shape; 

template <class T> 
ostream& operator<< (ostream& os, const Shape<T>& x); 

template <class T> 
class Shape { 
    T val; // do you really need val_new? 
public: 
    Shape(T initval) : val(initval) {} 
    T & get() { return val; } 
    void set (T const & newval) { val = newval; } 
    // not sure why you used and set val_new instead of val... 
    friend ostream& operator<< <> (ostream& os, const Shape<T>& x); 
}; 

class Rectangle { 
private: 
    Shape<TwoPoint> val; 
    bool incr_called, decr_called, load_called; 
    TwoPoint newval; 
public: 
    Rectangle(TwoPoint i) : val(Shape<TwoPoint> (i)), 
     incr_called(false), decr_called(false), load_called(false) {}  
    Shape<TwoPoint> & read() { return val; } 
    void load(const TwoPoint& n) { load_called = true; newval = n; } 
    void increment() { incr_called = true; } 
    void decrement() { decr_called = true; } 
    void init() { incr_called = decr_called = load_called = 0; } 
    void actions() { 
     if (load_called) { 
      val.set(TwoPoint(newval)); 
      load_called = false; // should the flag be reset? 
     } 
     if(incr_called && !decr_called) { 
      val.set(val.get().plus(1)); 
      incr_called = false; // should the flag be reset? 
     } 
     if(!incr_called && decr_called) { 
      val.set(val.get().plus(-1)); 
      decr_called = false; // should the flag be reset? 
     } 
    }  
    friend ostream& operator<< (ostream& os, const Rectangle& x); 
}; 

// added for debug printouts: 
ostream& operator<< (ostream& os, const TwoPoint& x){ 
    os << "TwoPoint(" << x.value << ", " << x.width << ")"; 
    return os; 
} 
template <class T> 
ostream& operator<< (ostream& os, const Shape<T>& x){ 
    os << "Shape(" << x.val << ")"; 
    return os; 
} 
ostream& operator<< (ostream& os, const Rectangle& x){ 
    os << "Rectangle(" << x.val 
    << (x.load_called ? ", load_called" : "") 
    << (x.incr_called ? ", incr_called" : "") 
    << (x.decr_called ? ", decr_called" : "") 
    << ")"; 
    return os; 
} 

int main() { 
    TwoPoint tp(800, 300); 
    cout << "Creating a Rectangle using " << tp << endl; 
    Rectangle r(tp); 
    cout << r << endl; 
    r.load(TwoPoint(100, 200)); 
    cout << r << endl; 
    r.actions(); 
    cout << r << endl; 
    r.increment(); 
    cout << r << endl; 
    r.actions(); 
    cout << r << endl; 
    r.decrement(); 
    cout << r << endl; 
    r.actions(); 
    cout << r << endl; 
    return 0; 
} 

而且程序的輸出:

Creating a Rectangle using TwoPoint(800, 300) 
Rectangle(Shape(TwoPoint(800, 300))) 
Rectangle(Shape(TwoPoint(800, 300)), load_called) 
Rectangle(Shape(TwoPoint(100, 200))) 
Rectangle(Shape(TwoPoint(100, 200)), incr_called) 
Rectangle(Shape(TwoPoint(101, 200))) 
Rectangle(Shape(TwoPoint(101, 200)), decr_called) 
Rectangle(Shape(TwoPoint(100, 200))) 

我希望開發這個應用程序時進一步此調試東西證明是有用的。