我拥有的模板是:
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));
}
};
TwoPoint类定义为:
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]
由于同样的原因,当我在actions()中执行类似操作时,还有两个错误。有人可以解释这些错误以及如何改进它们吗? 有什么方法可以让代码更有效率?
答案 0 :(得分: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));
}
有什么方法可以让代码更有效率?
动态分配通常比使用自动对象效率低 - 修复错误也消除了低效率的来源。
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 :(得分: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 ) ) )
我希望这个调试内容在进一步开发这个应用程序时证明是有用的。
答案 2 :(得分:1)
你有这个:
(new TwoPoint(val.get())).plus(1)
new
会返回指向TwoPoint
的指针,因此您必须使用->
代替.
来访问成员函数。
但是,如果你这样做,你会在一般情况下得到内存泄漏。我建议重新考虑你的设计,这样你就不需要动态分配东西了。