表达式节点的模板构造函数返回错误的值

时间:2016-08-31 22:21:50

标签: c++ templates constructor copy

我有一个模板类,似乎在一次测试中失败了。

  • 有一个模板结构" term"表示表达式图的节点值。
  • 有一个模板结构"表达"代表图表。
  • 有一个测试程序" void Test()"

我现在已经打了几个小时。我真的很想得到一些帮助。

void Test()
{
    cout << "****  Integer Tests" << endl;
    // Default Constructor
    integer a;
    cout << "integer a = "<< a.Value << endl;
    // Copy Constructor
    integer b(a);
    cout << "integer b(a) = "<< b.Value << endl;
    integer c = b;
    cout << "integer c = b = "<< c.Value << endl;
    // Type Constructor
    integer d(5);
    cout << "integer d(5) = "<< d.Value << endl;
    integer e = 5;
    cout << "integer e = 5 = "<< e.Value << endl;
    // Type Conversions
    int n = e.Value;
    cout << "n = e = "<< n << endl;/
    n = (int)d.Value + (int)e.Value;
    cout << "n = d + e = "<< n << endl;// allowed because a convers to int

    cout << "****  Expression Tests" << endl;
    expression<int> e1;
    expression<int> e2(e1);

    expression<int> e3(d);// This line using the copy constructor works
    expression<int> e4 = d + e;// this line, using the copy constructor AFTER the operator+ call results in BUM values.

}

测试功能&#34; void Test()&#34;未能为该陈述提供正确的值:

表达式e4 = d + e;

单步执行调用堆栈...在T + 1

1。)调用term :: expression&amp; operator +(term&amp; ref)

2。)返回时,表达式节点的左右值是CORRECT !!!

3。)现在,失败的赋值...它调用复制构造函数表达式(表达式和参考值)

4。)WTF ???在这里,我得到了左右两个值。

为什么,当复制构造函数测试在上面的行成功时?

这是测试用例模板

template<typename T> struct expression; // Forward Declare expressions, so i can use it in operator+

template<typename T>
struct term
{
    T Value;
    term() : Value(0) 
    { 
        cout << "****  term()" << endl;
    } // Default Constructor
    term(term& ref) : Value(ref.Value) 
    { 
        cout << "****  term(term& ref)" << endl;
    } // Copy Constructor
    // Type Conversion
    term(T value) : Value(value) 
    { 
        cout << "****  term(T value)" << endl;
    } // Type Constructor
    //operator T() const { return Value; } // Type Converter
    **expression<T>& operator+(term& ref) 
    {
        return expression<T>(*this, ref);
    };**
};

template<typename T>
struct expression
{
    term<T> Left;
    term<T> Right;
    expression() 
        : Left()
        , Right() 
    { 
        cout << "****  expression()" << endl;
        cout << "left" << Left.Value << endl;
        cout << "right" << Right.Value << endl;
    }
    expression(expression& ref) 
        : Left(ref.Left)
        , Right(ref.Right) 
    { 
        cout << "****  expression(expression& ref)" << endl;
        cout << "left" << Left.Value << endl;
        cout << "right" << Right.Value << endl;
    }
    expression(term<T>& left) 
        : Left(left)
        , Right() 
    { 
        cout << "****  expression(term<T>& left)" << endl;
        cout << "left" << Left.Value << endl;
        cout << "right" << Right.Value << endl;
    }
    expression(term<T>& left, term<T>& right) 
        : Left(left)
        , Right(right) 
    { 
        cout << "****  expression(term<T>& left, term<T>& right)" << endl;
        cout << "left" << Left.Value << endl;
        cout << "right" << Right.Value << endl;
    }
};
struct integer : public term<int> 
{ 

    integer() : term() { }// allows default constructor (not inheritablle)
    // tactic to get base class constructors(1 parameter) to compile...
    template<class T> integer(T t) : term(t) { }
    //template<class T> integer(T& t) : term(t) { }
};
void Test()
{
    cout << "****  Integer Tests" << endl;
    // Default Constructor
    integer a;
    cout << "integer a = "<< a.Value << endl;// allowed because integer converts to int
    // Copy Constructor
    integer b(a);
    cout << "integer b(a) = "<< b.Value << endl;
    integer c = b;
    cout << "integer c = b = "<< c.Value << endl;
    // Type Constructor
    integer d(5);
    cout << "integer d(5) = "<< d.Value << endl;
    integer e = 5;
    cout << "integer e = 5 = "<< e.Value << endl;
    // Type Conversions
    int n = e.Value;
    cout << "n = e = "<< n << endl;// allowed because a convers to int
    // Arithmetic using base type operators... whatever they allow, is allowed.
    n = (int)d.Value + (int)e.Value;
    cout << "n = d + e = "<< n << endl;// allowed because a convers to int

    cout << "****  Expression Tests" << endl;
    expression<int> e1;
    expression<int> e2(e1);

    expression<int> e3(d);// This line using the copy constructor works
    expression<int> e4 = d + e;// this line, using the copy constructor AFTER the operator+ call results in BUM values.

}

上述代码的输出如下:

****  Integer Tests
****  term()
integer a = 0
****  term(term& ref)
integer b(a) = 0
****  term(term& ref)
integer c = b = 0
****  term(T value)
integer d(5) = 5
****  term(T value)
integer e = 5 = 5
n = e = 5
n = d + e = 10
****  Expression Tests
****  term()
****  term()
****  expression()
left0
right0
****  term(term& ref)
****  term(term& ref)
****  expression(expression& ref)
left0
right0
****  term(term& ref)
****  term()
****  expression(term<T>& left)
left5
right0
****  term(term& ref)
****  term(term& ref)
****  expression(term<T>& left, term<T>& right)
left5
right5
****  term(term& ref)
****  term(term& ref)
****  expression(expression& ref)
left4061292
right4061296

编辑:正如所指出的那样(很快,我可能会补充),operator +正在返回对堆栈上temp的引用,而不是我假设的值。

修复该功能,以便除去表达后的&符号:

expression<T> operator+(term& ref) 
    {
        return expression<T>(*this, ref);
    };

这是ID10T错误。 &符号就在我面前。

再次,感谢您帮我解决此问题。

1 个答案:

答案 0 :(得分:2)

这是你的问题:

expression<T>& operator+(term& ref) 

operator+应该返回一个新对象。您正在返回对临时的引用。这应该甚至可以编译,但是我猜测你正在使用MSVC,它有一个扩展允许这个我不明白的原因。

您的代码中存在其他问题,应该阻止其编译,但这可能是导致您的错误的问题。作为第一个近似值,代码中每次使用引用都是错误的 - 它们都应该是对const或值的引用。