概述
练习7.41
#ifndef ex7_41_H
#define ex7_41_H
#include <string>
#include <iostream>
//类声明
class Sales_data;
//函数声明
std::istream &read(std::istream &, Sales_data &);
class Sales_data {
//友元函数声明,类外部函数read和print可以访问类内数据成员(公有和私有)
friend std::istream &read(std::istream &, Sales_data &);
friend std::ostream &print(std::ostream &, const Sales_data &);
public:
//非委托构造函数,接受三个参数,使用实参初始化数据成员,然后结束工作
Sales_data(const std::string &s, unsigned n, double p):
bookNo(s), units_sold(n), revenue(p*n) {}
//定义默认构造函数,令其委托三参数的构造函数完成默认构造的初始化过程
//此默认构造函数是委托构造函数
Sales_data() : Sales_data("", 0, 0) {};
//定义接受一个string的构造函数,令其委托三参数的构造函数完成该构造函数的初始化过程
//这里接受一个string的构造函数是委托构造函数
Sales_data(const std::string &s) : Sales_data(s, 0, 0) { }
//定义一个接受istream&的构造函数,令其委托三参数的构造函数完成该构造函数的初始化过程
//当这些受委托的构造函数执行完后,接着执行istream&构造函数体的内容
Sales_data(std::istream &is) : Sales_data("", 0, 0) { read(is, *this); }
//成员函数isbn定义
//const修饰隐式参数this指针(存着对象的地址),表明this所指对象不能改变(包含对象的数据成员)
std::string isbn() const { return bookNo; }
//成员函数combine声明,返回类型为引用类型(非拷贝值)
Sales_data &combine(const Sales_data&);
private:
//显式内联函数声明
inline double ave_price() const;
//数据成员
std::string bookNo;
unsigned units_sold = 0;
double revenue = 0.0;
};
//函数定义,函数avg_price在类Sales_data的作用域内
inline double Sales_data::avg_price() const
{
return units_sold ? revenue/units_sold : 0;
}
//函数定义,函数combine在类Sales_data的作用域内
//形参为引用类型,函数体中对形参的操作就是对实参的操作
//const使得函数体中无法改变形参rhs(实则是实参)的值
Sales_data& Sales_data::combine(const Sales_data &rhs) {
units_sold += rhs.units_sold;
revenue += rhs.revenue;
return *this;//解引用this获得对象,返回对象引用(对象的原值被修改,而非其拷贝值被修改)
}
Sales_data add(const Sales_data &lhs, const Sales_data &rhs)
{
Sales_data sum = lhs;
sum.combine(rhs);
return sum;//返回拷贝值给临时对象
//在调用函数add的地方会将函数返回值复制给临时对象
}
//读写一个IO对象会改变其状态,因此传递和返回的引用不能是const的,如Sales_data &item
std::istream &read(std::istream &is, Sales_data &item)
{
double price = 0;
is >> item.bookNo >> item.units_sold >> price;
item.revenue = price * item.units_sold;
return is;
}
std::ostream &print(std::ostream &os, const Sales_data &item)
{
os << item.isbn() << " " << item.units_sold << " " << item.revenue;
return os;
}
#endif
练习7.42
练习7.40中编写的类
class Book{
public:
Book() = default;
Book(unsigned no, std::string name, std::string author, std::string pubdate):no_(no),name_(name),author_(author),pubdate_(pubdate){ }
Book(std::istream &in) { in >> no_ >> name_ >> author_ >> pubdate; }
private:
unsigned no_;
std::string name_;
std::string author_;
std::string pubdate_;
};
练习7.42
class Book{
public:
Book(unsigned no, std::string name, std::string author, std::string pubdate):no_(no),name_(name),author_(author),pubdate_(pubdate){ }
默认构造函数委托给Book(0,"","")完成其初始化过程,后执行Book()的函数体,即结束工作
Book() : Book(0,"",""){}
//一个参数的Book构造函数将其初始化过程委托给默认构造函数,但默认构造函数又委托给Book(0,"",""),
//所以最终Book(0,"","")会完成Book(std::istream &in)的初始化过程,
//接着执行该函数的函数体{ in >> no_ >> name_ >> author_ >> pubdate; }
Book(std::istream &in) : Book() { in >> no_ >> name_ >> author_ >> pubdate; }
private:
unsigned no_;
std::string name_;
std::string author_;
std::string pubdate_;
};
练习7.43
#include <vector>
class NoDefault {
public:
NoDefault(int i) { }
};
class C {
public:
//C的构造函数
C() : def(0) { }
private:
NoDefault def;
};
int main()
{
C c;
std::vector<C> vec(10);
return 0;
}
练习7.44
illegal, cause there are ten elements, each would be default initialized. But no default initializer for the temporary object
NoDefault类中没有默认构造函数
练习7.45
vector<C> vec(10);
No problem. cause c have the default constructor
练习7.46
- untrue,The compiler-generated constructor is known as the synthesized default constructor
- untrue, A default constructor is a constructor that is used if no initializer is supplied. What’s more, A constructor that supplies default arguments for all its parameters also defines the default constructor
(默认构造函数是没有提供初始化程序的构造函数。 此外,为所有参数提供默认参数的构造函数还定义了默认构造函数)
- untrue, the class should provide
- untrue, only if our class does not explicitly(显式地) define any constructors, the complier will implicitly define the default constructor for us.
练习7.47
explicit Sales_data(std::istream&);
Whether the conversion fo a string to Sales_data is desired depends on how we think our users will use the conversion. In this case, it might be okay. The string in null_book probably represents a nonexistent ISBN.
是否需要将string转换为“ Sales_data”,取决于我们认为用户将如何使用转换。 在这种情况下,可能没问题。null_book中的“字符串”可能表示一个不存在的ISBN。
Benefits:
-
prevent the use of a constructor in a context that requires an implicit conversion
(防止在需要隐式转换的情况中使用构造函数) -
we can define a constructor which is used only with the direct form of initialization
(我们可以定义一个构造函数,该构造函数仅与直接初始化一起使用)
explicit Sales_data::Sales_data(istream& is){ read(is, *this); }
Sales_data item1(null_book); //直接初始化
Sales_data item2 = null_book; //错误:不能将explicit的构造函数用于拷贝初始化
Drawbacks:
- meaningful only on constructors that can be called with a single argument
(仅对可以使用单个参数调用的构造函数有意义)
练习7.48
Sales_data item1(null_isbn); //string类型没有转换为Sales_data类型
Sales_data item2("9-999-99999-9"); //string类型没有转换为Sales_data类型
练习7.49
(a)
Sales_data &combine(Sales_data); //ok
(b)
Sales_data &combine(Sales_data&);//Error
//no matching function for call to 'Sales_data::combine(std::string&)'
//('std::string&' can not convert to 'Sales_data' type)
(c)
Sales_data &combine(const Sales_data&) const;
//The trailing const mark can't be put here,as it forbids any mutation on data members.(不能在其后加上const标记,因为它禁止对数据成员进行任何更改 )
//This conflicts with combine's semantics(这个与combine的语义冲突)
练习7.50
#ifndef ex7_50_h
#define ex7_50_h
#include <string>
#include <iostream>
struct Person {
friend std::istream &read(std::istream &is, Person &person);
friend std::ostream &print(std::ostream &os, const Person &person);
public:
Person() = default;
Person(const std::string sname, const std::string saddr):name(sname), address(saddr){ }
//explicit抑制构造函数定义的隐式类类型转换
explicit Person(std::istream &is){ read(is, *this); }
std::string getName() const { return name; }
std::string getAddress() const { return address; }
private:
std::string name;
std::string address;
};
//读写一个IO对象会改变其状态,因此传递和返回的引用不能是const的,如Person &person
//形参为引用类型,形参与实参进行绑定,避免拷贝实参
std::istream &read(std::istream &is, Person &person)
{
is >> person.name >> person.address;
return is;//返回类型为引用
}
//形参为引用类型,形参与实参进行绑定,避免拷贝实参
std::ostream &print(std::ostream &os, const Person &person)
{
os << person.name << " " << person.address;
return os;//返回类型为引用
}
#endif
练习7.51
Such as a function like that:
int getSize(const std::vector<int>&);
if vector has not defined its single-argument constructor as explicit. we can use the function like:
getSize(34); //34为整型 而函数形参类型为vector类型,但vector元素类型却是整型
What is this mean? it’s very confused.
But the std::string is different. In ordinary, we use std::string to replace const char *(the C language). so when we call a function like that:
void setYourName(std::string); //声明
setYourName("pezy"); //just fine
最后
以上就是寒冷蜜蜂为你收集整理的c++primer练习7.41、7.42、7.43、7.44、7.45、7.46、7.47、7.48、7.49、7.50练习7.41练习7.42练习7.43练习7.44练习7.45练习7.46练习7.47练习7.48练习7.49练习7.50练习7.51的全部内容,希望文章能够帮你解决c++primer练习7.41、7.42、7.43、7.44、7.45、7.46、7.47、7.48、7.49、7.50练习7.41练习7.42练习7.43练习7.44练习7.45练习7.46练习7.47练习7.48练习7.49练习7.50练习7.51所遇到的程序开发问题。
如果觉得靠谱客网站的内容还不错,欢迎将靠谱客网站推荐给程序员好友。
发表评论 取消回复