【问题标题】:About friend function in C++关于 C++ 中的友元函数
【发布时间】:2015-01-26 14:55:57
【问题描述】:

Sales_data.h

#ifndef SALES_DATA_H
#define SALES_DATA_H
#include <string>

class Sales_data {
    friend std::istream &read(std::istream &in, Sales_data &data);
    friend std::ostream &print(std::ostream &out, const Sales_data &data);

public:
    Sales_data() = default;
    //Sales_data(std::string _bookNo="", unsigned _units_sold = 0, double _revenue = 0)
        //:bookNo(_bookNo), units_sold(_units_sold), revenue(_revenue) {}
    std::string isbn() { return bookNo; }
    Sales_data& combine(const Sales_data&);
    double avg_price() const;
private:
    std::string bookNo;
    unsigned units_sold = 0;
    double revenue = 0;
};

Sales_data &Sales_data::combine(const Sales_data& data) {
    units_sold += data.units_sold;
    revenue += data.revenue;
    return *this;
}

std::istream &read(std::istream &in, Sales_data &data);
std::ostream &print(std::ostream &out, const Sales_data &data);

#endif

Sales_data.cpp

#include "Sales_data.h"

/*
double Sales_data::avg_price() const {
    return units_sold != 0 ? (revenue / units_sold) : 0;
}
*/

std::istream &read(std::istream &in, Sales_data &data) {
    in >> data.bookNo >> data.units_sold >> data.revenue;
    return in;
}

std::ostream &print(std::ostream &out, Sales_data &data) {
    out << data.isbn() << " " << data.units_sold << " " << data.revenue;
    return out;
}

main_func.cpp

#include "Sales_data.h"
#include <iostream>
using std::cin;
using std::cout;
using std::cerr;
using std::endl;

void func() {
    Sales_data total;
    if(read(cin, total)) {
        Sales_data trans;
        while(read(cin, trans)) {
            if (total.isbn() == trans.isbn())
                total.combine(trans);
            else {
                print(cout, total) << endl;
                total = trans;
            }
        }
        print(cout, total) << endl;
    } else {
        cerr << "No data?!" << endl;
    }
}

int main(int argc, char** argv) {
    func();
    return 0;
}

我运行程序,但它总是告诉我有问题。我确实使用了朋友功能,但它仍然说我使用类的私有成员。信息流: Sales_data.cpp:10:23: error: invalid operands to binary expression ('basic_istream<char>' and 'unsigned int') in >> data.bookNo >> data.units_sold >> data.revenue; ~~~~~~~~~~~~~~~~~ ^ ~~~~~~~~~~~~~~~ /usr/bin/../lib/gcc/x86_64-redhat-linux/4.8.2/../../../../include/c++/4.8.2/bits/basic_string.tcc:996:5: note: candidate template ignored: could not match 'basic_string<type-parameter-0-0, type-parameter-0-1, type-parameter-0-2>' against 'unsigned int' operator>>(basic_istream<_CharT, _Traits>& __in, ^ Sales_data.cpp:15:24: error: invalid operands to binary expression ('basic_ostream<char, std::char_traits<char> >' and 'const char *') out << data.isbn() << " " << data.units_sold << " " << data.revenue; ~~~~~~~~~~~~~~~~~~ ^ ~~~ /usr/bin/../lib/gcc/x86_64-redhat-linux/4.8.2/../../../../include/c++/4.8.2/bits/basic_string.h:2753:5: note: candidate template ignored: could not match 'basic_string<type-parameter-0-0, type-parameter-0-1, type-parameter-0-2>' against 'char const[2]' operator<<(basic_ostream<_CharT, _Traits>& __os, ^ Sales_data.cpp:15:39: error: 'units_sold' is a private member of 'Sales_data' out << data.isbn() << " " << data.units_sold << " " << data.revenue; ^ ./Sales_data.h:18:14: note: declared private here unsigned units_sold = 0; ^ Sales_data.cpp:15:65: error: 'revenue' is a private member of 'Sales_data' out << data.isbn() << " " << data.units_sold << " " << data.revenue; ^ ./Sales_data.h:19:12: note: declared private here double revenue = 0; ^ 4 errors generated.

【问题讨论】:

  • 您忘记包含&lt;iostream&gt;
  • @MikeSeymour 谢谢,我确实忘记包含文件了。
  • 另外combine函数不能在.h文件中定义,否则会出现链接重复错误。所以将其移至 .cpp 或使其内联。
  • @Zoka Hive 修复了它。谢谢!

标签: c++ c++11 g++ clang++ friend-function


【解决方案1】:

由于Sales_data &amp;const Sales_data &amp; 是不同的类型,cpp 文件中的print 函数被认为是print 函数的单独重载,这不是你Sales_data班级的朋友。

添加const 以修复此错误:

std::ostream &print(std::ostream &out, const Sales_data &data) {
... //                                 ^^^^^
}

【讨论】:

  • 要使建议的解决方案正常工作,您还需要使 isbn 函数 const 也:std::string isbn() const { return bookNo; }(通过使函数 const 你说,调用此函数不会更改任何内部数据类。
  • @Zoka 是的!我修好了。
  • 我用命令clang++ 8.6.cpp Sales_data.cpp -std=c++11编译程序,但它告诉我/tmp/Sales_data-08bdcf.o: In function Sales_data::combine(Sales_data const&)': Sales_data.cpp:(.text+0x0): 多重定义Sales_data::combine(Sales_data const&amp;)' /tmp/8-b9582d.o:8.6.cpp:(.text+0x0): first defined here clang: error: linker command failed with exit code 1 (use -v to see invocation)
  • @Sparks_Fly 第二个错误是因为您将combine 的实现放在了标题中,但在类声明之外。您应该将其移至声明中,或将其移至 cpp 文件中。
  • @Zoka 从技术上讲你是对的,但由于目标似乎是展示友谊,这里真正的错误是使用“data.isbn()”,而不是“data.bookNo”。作为朋友,print() 函数可以访问私有 data.bookNo,但调用 data.isbn() 失败,因为在 print() 中,data 是一个 const 引用,因此只能调用 const 成员函数 - 正如你所指出的出来。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 2018-08-11
  • 2018-11-06
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多