如何正确定义和调用原始运算符<<

时间:2017-12-28 15:43:47

标签: c++ operator-overloading

考虑以下示例:

<?php
// .......

$sql = "(Select Ad.[Act] 'Act', Ad.[Units] 'Units', Ad_Acts.[Name] from Ad JOIN Ad_Act ON Ad.ActID = Ad_Act.ActAttend)
        Union ALL(Select Citi.[Act2] 'Act', Citi.[Units2] 'Units', Citi_act.[Name] from Citi JOIN Citi_Acts ON Citi.ActID2 = Citi_Act.ActAttend2)
         Union ALL(Select ComOut.[Act3] 'Act', ComOut.[Units3] 'Units', ComOut_Act.[Name] from ComOut JOIN ComOut_Act ON ComOut.ActID3 = ComOut_Act.ActAttend3)
         Union ALL(Select ReSchAct.[Act4] 'Act', ReSchAct.[Units4] 'Units', ReSch_Act.[Name] from ReSchAct JOIN ReSch_Act ON ReSchAct.ActID4 = ReSch_Act.ActAttend4)
          Union ALL(Select TeEd.[Act5] 'Act', TeEd.[Units5] 'Units', TeEd_Act.[Name] from TeEd JOIN TeEd_Act ON TeEd.ActID5 = TeEd_Act.ActAttend5)";

//  ........

$totalUnits = 0;
?>

<table>
    <tr>
        <th>Act</th>
        <th>Units</th>
        <th>Name</th>
    </tr>
<?php while($row = sqlsrv_fetch_array($stmt, SQLSRV_FETCH_ASSOC)) : ?>
    <tr>
        <td><?php echo $row['Act']</td>
        <td><?php echo $row['Units']</td>
        <td><?php echo $row['Name']</td>
    </tr>
    <?php $totalUnits = $totalUnits + intval($row['Units']); ?>
<?php endwhile; ?>
    <tr>
        <td></td>
        <td>Total Units: </td>
        <td><?php echo $totalUnits; ?></td>
    </tr>
</table>

它将生成以下输出:

#include <iostream>

class A {
    const int i;
    const int j;

public:
    A(int i_, int j_) : i(i_), j(j_) {}

    std::ostream& operator<<(std::ostream& o) const {
       o << "i is " << i << ", j is " << j;
       return o;
    }
};

std::ostream& operator<<(std::ostream& o, const A& a ) {
    o << "This is A: ";
    a.operator<<(o);

    return o;
}

int main() {
    A a(0,42);

    std::cout << a << std::endl;
    return 0;
}

输出正确,但我不喜欢我如何调用A的原始This is A: i is 0, j is 42

我试图找出如何正确定义该运算符,因此可以这样调用:

operator<<

而不是

o << "This is A: " << (some magic)a;

我尝试了各种方法,但要么是出现模糊问题,要么是获取o << "This is A: "; a.operator<<(o); 和破坏字符串的地址。请注意,std::cout的结果std::ostream&是我测试的残余。在上面的示例中,只需使用A::operator<<

是否可以在不创建从类A派生的中间类B的情况下定义自己的运算符&lt;&lt; (void)?

2 个答案:

答案 0 :(得分:3)

在类中定义的二进制运算符始终将该类作为左侧操作数。这意味着你无法在课堂上实现流插入/提取。

可能最常见的方法是将运算符实现为类中内联定义的friend

另一种相当常见的方法是在类中提供命名的流功能,以及调用该功能的类外流操作符。你几乎做到了,但命名为operator <<

答案 1 :(得分:0)

我最接近的解决方案是创建一个中间类:

class Decorate {
    const A& a;

public:
    Decorate(const A& a_) : a(a_) {}

    friend std::ostream& operator<<(std::ostream& o, const PrintA& pa) {
        o << "This is A: " << pa.a;
        return o;
    }
};

以这种方式打印:

int main() {
    A a(0,42);

    std::cout << Decorate(a) << std::endl;
    return 0;
}

我正在寻找更漂亮的东西,但根据Angew的回答,我失去了希望让它完成正确的operator<<声明。

感谢您的帮助! 将Angew的回应标记为答案。