zoukankan      html  css  js  c++  java
  • 类5(转换构造函数)

    转换构造函数:

    当一个构造函数只有一个参数,而且该参数又不是本类的const引用时,这种构造函数称为转换构造函数。

    转换构造函数的作用是将一个其他类型的数据转换成一个类的对象。注意:转换构造函数只能有一个参数。如果有多个参数,就不是转换构造函数:

     1 #include <iostream>
     2 using namespace std;
     3 
     4 class Sales_data{
     5     
     6     //数据成员
     7 private:
     8     std::string book_no;
     9     unsigned units_sold = 1;
    10     double revenue = 1.0;
    11 
    12 public:
    13     Sales_data() = default;//不接受任何实参,默认构造函数
    14     Sales_data(const std::string &s): book_no(s){}//只有一个形参,类型转换构造函数
    15     Sales_data(const std::string &s, unsigned n, double p): book_no(s), units_sold(n), revenue(p * n){}
    16     Sales_data(std::istream&);
    17 
    18     Sales_data operator+=(const Sales_data &it){
    19         book_no += it.book_no;
    20         units_sold += it.units_sold;
    21         revenue += it.revenue;
    22         return *this;
    23     }
    24 
    25     void out_put(std::ostream &os){
    26         os << book_no << " " << units_sold << " " << revenue << std::endl;
    27     }
    28 
    29     Sales_data& combine(const Sales_data&);
    30 };
    31 
    32 Sales_data& Sales_data::combine(const Sales_data &rhs){
    33     book_no += rhs.book_no;
    34     units_sold += rhs.units_sold;
    35     revenue += rhs.revenue;
    36     return *this;
    37 }
    38 
    39 // Sales_data operator+(const Sales_data &it1, const Sales_data &it2);
    40 
    41 int main(void){
    42     Sales_data("jfl");//构造一个临时Sales_data对象
    43     Sales_data cnt("hello");
    44     string null_book = " world";
    45     cnt.combine(null_book);//null_book被自动转换成Sales_data对象并绑定到引用变量rhs上,
    46     // 构造出的临时Sales_data对象中book_no值为null_book,units为1,revenue为1.0
    47     // cnt.combine(" world");//需要进行两步类型转换,error(" world"要先转换为string类型,然后再转换成Sales_data类型)
    48     cnt.out_put(cout);//输出hello world 2 2
    49     cnt += null_book;//同上,null_book被自动转换成Sales_data对象
    50     cnt.out_put(cout);//输出hello world world 3 3
    51     return 0;
    52 }

     还需要注意的是:编译器只会自动地执行一步类型转换。所以在上例中 cnt.combine("world");和 cnt += "world");都是错误的,因为其隐式的使用了两种转换规则,先把 "world" 转换成 string,再把这个临时 string 变量转换成 Sales_data。要使上面调用变成正确的,我们可以先将 "world" 显示的转换成 string 或者 Sales_data:

    1     cnt.combine(string("world"));
    2     cnt.combine(Sales_data("world"));
    3     cnt += string("world");
    4     cnt += Sales_data("world");

    类型转换函数不总是有效:

    是否需要从 string 到 Sales_data 的转换依赖于我们对用户使用该转换的看法。在上面的例子中,这种转换可能是对的。 null_book 中的 string 可能表示了一个不存在的 isbn 编号。

    但是如果将一个 istream 对象 cin 转换为 Sales_data 的话,显然不是我们想要的结果:

     1 #include <iostream>
     2 using namespace std;
     3 
     4 class Sales_data{
     5 friend std::istream &read(std::istream&, Sales_data&);
     6     
     7     //数据成员
     8 private:
     9     std::string book_no;
    10     unsigned units_sold = 1;
    11     double revenue = 1.0;
    12 
    13 public:
    14     Sales_data() = default;//不接受任何实参,默认构造函数
    15     Sales_data(const std::string &s): book_no(s){}//只有一个形参,类型转换构造函数
    16     Sales_data(const std::string &s, unsigned n, double p): book_no(s), units_sold(n), revenue(p * n){}
    17     Sales_data(std::istream&);//只有一个形参,类型转换构造函数
    18 
    19     void out_put(std::ostream &os){
    20         os << book_no << " " << units_sold << " " << revenue << std::endl;
    21     }
    22 
    23     Sales_data& combine(const Sales_data&);
    24 };
    25 
    26 Sales_data& Sales_data::combine(const Sales_data &rhs){
    27     book_no += rhs.book_no;
    28     units_sold += rhs.units_sold;
    29     revenue += rhs.revenue;
    30     return *this;
    31 }
    32 
    33 std::istream &read(std::istream&, Sales_data&);
    34 
    35 Sales_data::Sales_data(std::istream &is){
    36     read(is, *this);
    37 }
    38 
    39 istream &read(istream &is, Sales_data &item){
    40     double price = 0;
    41     is >> item.book_no >> item.units_sold >> price;
    42     item.revenue = price * item.units_sold;
    43     return is;
    44 }
    45 
    46 int main(void){
    47     Sales_data cnt("hello");
    48     cnt.combine(cin);
    49     cnt.out_put(cout);
    50     return 0;
    51 }

    cnt.combine(cin);先执行转换构造函数 

    Sales_data::Sales_data(std::istream &is)

    将 cin 转换成 Sales_data 类型,因为该函数体中又调用了 read 函数,所以会产生输入。构造的临时 Sales_data 对象的初始化数据由输入数据产生。因此最终输出:helloworld 2 2

    抑制构造函数定义的隐式转换:

    我们可以通过将构造函数声明为 explicit 阻止构造转换函数的隐式转换:

     1 #include <iostream>
     2 using namespace std;
     3 
     4 class Sales_data{
     5 friend std::istream &read(std::istream&, Sales_data&);
     6     
     7     //数据成员
     8 private:
     9     std::string book_no;
    10     unsigned units_sold = 1;
    11     double revenue = 1.0;
    12 
    13 public:
    14     Sales_data() = default;//不接受任何实参,默认构造函数
    15     explicit Sales_data(const std::string &s): book_no(s){}//加了explicit关键字
    16     Sales_data(const std::string &s, unsigned n, double p): book_no(s), units_sold(n), revenue(p * n){}
    17     explicit Sales_data(std::istream&);//加了explicit关键字
    18 
    19     void out_put(std::ostream &os){
    20         os << book_no << " " << units_sold << " " << revenue << std::endl;
    21     }
    22 
    23     Sales_data& combine(const Sales_data&);
    24 };
    25 
    26 Sales_data& Sales_data::combine(const Sales_data &rhs){
    27     book_no += rhs.book_no;
    28     units_sold += rhs.units_sold;
    29     revenue += rhs.revenue;
    30     return *this;
    31 }
    32 
    33 std::istream &read(std::istream&, Sales_data&);
    34 
    35 Sales_data::Sales_data(std::istream &is){
    36     read(is, *this);
    37 }
    38 
    39 istream &read(istream &is, Sales_data &item){
    40     double price = 0;
    41     is >> item.book_no >> item.units_sold >> price;
    42     item.revenue = price * item.units_sold;
    43     return is;
    44 }
    45 
    46 int main(void){
    47     Sales_data cnt("hello");
    48     // cnt.combine(cin);//error
    49     // cnt.combine(string("world"));//error
    50     return 0;
    51 }

    加了 explicit 关键字后 cnt.combine(cin);cnt.combine(string("world"));都是错误的。

    explicit 关键字只对一个实参的构造函数有效。需要多个实参的构造函数不能用于执行隐式转换,所以无需将需要多个实参的构造函数声明成 explicit 的,虽然这样做也并没有语法错误。explicit 只能在类内声明构造函数时使用,在外部定义时不应该重复。

    explicit 关键字声明的构造函数只能用于直接初始化:

    Sales_data cnt(null_book);
    Sales_data gel = null_book;

    如果没有将对应的构造函数声明成 explicit 的话,这两者初始化方式都是可以的,反之则只有值即初始化是正确的,而拷贝初始化是错误的。

    为转换而显示的使用构造函数:

    尽管编译器不会将 explicit 的构造函数用于隐式的转换,但是我们可以这样的构造函数显示地强制进行转换:

     1 #include <iostream>
     2 using namespace std;
     3 
     4 class Sales_data{
     5 friend std::istream &read(std::istream&, Sales_data&);
     6     
     7     //数据成员
     8 private:
     9     std::string book_no;
    10     unsigned units_sold = 1;
    11     double revenue = 1.0;
    12 
    13 public:
    14     Sales_data() = default;//不接受任何实参,默认构造函数
    15     explicit Sales_data(const std::string &s): book_no(s){}//加了explicit关键字
    16     Sales_data(const std::string &s, unsigned n, double p): book_no(s), units_sold(n), revenue(p * n){}
    17     explicit Sales_data(std::istream&);//加了explicit关键字
    18 
    19     Sales_data &operator+=(const Sales_data &it){
    20         book_no += it.book_no;
    21         units_sold += it.units_sold;
    22         revenue += it.revenue;
    23         return *this;
    24     }
    25 
    26     void out_put(std::ostream &os){
    27         os << book_no << " " << units_sold << " " << revenue << std::endl;
    28     }
    29 
    30     Sales_data& combine(const Sales_data&);
    31 };
    32 
    33 Sales_data& Sales_data::combine(const Sales_data &rhs){
    34     book_no += rhs.book_no;
    35     units_sold += rhs.units_sold;
    36     revenue += rhs.revenue;
    37     return *this;
    38 }
    39 
    40 std::istream &read(std::istream&, Sales_data&);
    41 
    42 Sales_data::Sales_data(std::istream &is){
    43     read(is, *this);
    44 }
    45 
    46 istream &read(istream &is, Sales_data &item){
    47     double price = 0;
    48     is >> item.book_no >> item.units_sold >> price;
    49     item.revenue = price * item.units_sold;
    50     return is;
    51 }
    52 
    53 int main(void){
    54     string cnt = "world";
    55     Sales_data gel("hello");
    56     gel.combine(Sales_data(cnt));//显示地强制类型转换
    57     gel += Sales_data(cnt);
    58     return 0;
    59 }
     
  • 相关阅读:
    JS闭包
    js Date日期对象的扩展
    python通过post提交数据的方法
    python通过post提交数据的方法
    在Python中操作文件之truncate()方法的使用教程
    在Python中操作文件之truncate()方法的使用教程
    大数据将使安全产品爆发式增长
    大数据将使安全产品爆发式增长
    Python中内置数据类型list,tuple,dict,set的区别和用法
    Python中内置数据类型list,tuple,dict,set的区别和用法
  • 原文地址:https://www.cnblogs.com/geloutingyu/p/8150019.html
Copyright © 2011-2022 走看看