我是靠谱客的博主 寒冷蜜蜂,最近开发中收集的这篇文章主要介绍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,觉得挺不错的,现在分享给大家,希望可以做个参考。

概述

练习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所遇到的程序开发问题。

如果觉得靠谱客网站的内容还不错,欢迎将靠谱客网站推荐给程序员好友。

本图文内容来源于网友提供,作为学习参考使用,或来自网络收集整理,版权属于原作者所有。
点赞(39)

评论列表共有 0 条评论

立即
投稿
返回
顶部