<C++primer> 7.12习题疑惑解答

问题起源:

直接将Sales_data(std::istream&is)构造函数移动到类内时,编译器报错

猜想:

1.可能是因为类构造函数内使用了read函数,而read函数形参为类对象,即因果关系颠倒

   导致read函数无法被正常调用

验证过程:

第一次尝试:将类外构造函数定义从源文件移动到头文件内,且在read函数声明之前

结果:编译器报错

第二次尝试:将类外构造函数定义从源文件移动到头文件内,且在read函数声明之后

结果:编译成功

std::istream& read(std::istream& is, Sales_data& d);
Sales_data::Sales_data(std::istream& is)
{
	read(is, *this);
}

这两次尝试对比我们可以知道:类外构造函数时,由于函数内部使用了read函数,所以定义构造函数时,需要在read函数声明之后(即在源文件中定义(read声明在头文件),或者在头文件且在read声明之后定义)

因此,如果要将类外构造函数在类的内部定义,则read函数声明一定要在该构造函数之前

第三次尝试:

3.1:将read声明在类内,构造函数之前(对应#1位置)

3.2:将read声明在类外,Sales_data之前(对应#2位置)

(注意:下图中,#1与#2代码不同时存在,每次仅存在一种)

结果:均编译失败

原因:

3.1:在类内的声明中, 构造函数优先声明,其次才按顺序声明,因此无论read放在类内哪个位置,声明均在构造函数之后

3.2:在类外的声明中,read确实声明比构造函数早,但read形参有Sales_data,此时Sales_data声明却比read晚,因此遇到了新的同类问题

std::istream& read(std::istream& is, Sales_data& d);//#1
struct Sales_data
{
	std::string bookno;
	unsigned units_sold = 0;
	double revenue = 0.0;

	Sales_data() = default;
	Sales_data(const std::string s) :bookno(s) {}
	Sales_data(const std::string s, const unsigned sd, const double r) :bookno(s), units_sold(sd), revenue(r) {}
    std::istream& read(std::istream& is, Sales_data& d);//#2
	Sales_data(std::istream& is);
	Sales_data& combine(Sales_data& d);
	std::string isbn()const
	{
		return bookno;
	}

};
Sales_data::Sales_data(std::istream& is)
{
	read(is, *this);
}

第四次尝试:

把类的声明和read函数的声明放置在构造函数前

结果:编译成功

struct Sales_data;
std::istream& read(std::istream& is, Sales_data& d);

struct Sales_data
{
	std::string bookno;
	unsigned units_sold = 0;
	double revenue = 0.0;

	Sales_data() = default;
	Sales_data(const std::string s) :bookno(s) {}
	Sales_data(const std::string s, const unsigned sd, const double r) :bookno(s), units_sold(sd), revenue(r) {}
	Sales_data(std::istream& is)
	{
		read(is, *this);
	}
	Sales_data& combine(Sales_data& d);
	std::string isbn()const
	{
		return bookno;
	}

};

以下是能正常运行的原程序文件:

头文件:

//头文件"Sales_data.h"
#ifndef SALESDATA
#define SALESDATA
#include<string>
struct Sales_data
{
	std::string bookno;
	unsigned units_sold=0;
	double revenue =0.0;
	
	Sales_data() = default;
	Sales_data(const std::string s):bookno(s) {}
	Sales_data(const std::string s,const unsigned sd,const double r):bookno(s),units_sold(sd),revenue(r){}
	Sales_data(std::istream& is);
	Sales_data& combine(Sales_data& d);
	std::string isbn()const
	{
		return bookno;
	}
	
};

std::istream &read(std::istream& is, Sales_data& d);
std::ostream &print(std::ostream& os, const Sales_data& d);
Sales_data& add(Sales_data& d1, Sales_data& d2);

#endif

源文件:

#include<iostream>
#include"Sales_data.h"

using namespace std;

Sales_data& Sales_data::combine(Sales_data& d)
{
	units_sold += d.units_sold;
	revenue += d.revenue;
	return *this;
}
std::istream& read(std::istream& is, Sales_data& d)
{
	double price = 0.0;
	is >> d.bookno >> d.units_sold >> price;
	d.revenue = d.units_sold * price;
	return is;
}
Sales_data& add(Sales_data& d1, Sales_data& d2)
{
	Sales_data sum=d1;
	sum.combine(d2);
	return sum;
}
std::ostream& print(std::ostream& os, const Sales_data& d)
{
	os << "isbn:" << d.isbn() << " " << " sells" << d.units_sold << " " << " and its revenue is: " << d.revenue << endl;
	return os;
}
Sales_data::Sales_data(std::istream& is)
{
	read(is, *this);
}


int main()
{
	
	
	if (cin)
	{
		Sales_data total(cin);
		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
	{
		std::cerr << "No data!" << endl;
	}

}

最后将构造函数放在类内部成功运行的程序代码:

头文件:

//头文件"Sales_data.h"
#ifndef SALESDATA
#define SALESDATA
#include<string>

struct Sales_data;
std::istream& read(std::istream& is, Sales_data& d);

struct Sales_data
{
	std::string bookno;
	unsigned units_sold = 0;
	double revenue = 0.0;

	Sales_data() = default;
	Sales_data(const std::string s) :bookno(s) {}
	Sales_data(const std::string s, const unsigned sd, const double r) :bookno(s), units_sold(sd), revenue(r) {}
	
	Sales_data(std::istream& is)
	{
		read(is, *this);
	}
	Sales_data& combine(Sales_data& d);
	std::string isbn()const
	{
		return bookno;
	}

};

std::ostream& print(std::ostream& os, const Sales_data& d);
Sales_data& add(Sales_data& d1, Sales_data& d2);

#endif

源文件:

#include<iostream>
#include"Sales_data.h"

using namespace std;

Sales_data& Sales_data::combine(Sales_data& d)
{
	units_sold += d.units_sold;
	revenue += d.revenue;
	return *this;
}
std::istream& read(std::istream& is, Sales_data& d)
{
	double price = 0.0;
	is >> d.bookno >> d.units_sold >> price;
	d.revenue = d.units_sold * price;
	return is;
}
Sales_data& add(Sales_data& d1, Sales_data& d2)
{
	Sales_data sum = d1;
	sum.combine(d2);
	return sum;
}
std::ostream& print(std::ostream& os, const Sales_data& d)
{
	os << "isbn:" << d.isbn() << " " << " sells" << d.units_sold << " " << " and its revenue is: " << d.revenue << endl;
	return os;
}



int main()
{


	if (cin)
	{
		Sales_data total(cin);
		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
	{
		std::cerr << "No data!" << endl;
	}

}

  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 1
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值