第12章 让对象像数值一样工作

自定义类产生的隐式类型转换:当构造函数有且仅有一个未指定默认值的参数的时候,可能会产生参数类型到自定义类型的隐式转换。例如:

class Test{

    int v_;

public:

    Test(int i) : v_(i){}

    int GetV() const{return v_;}

};

 

void fun(const Test& test)

{

    std::cout<<test.GetV();

}

 

int main()

{

    fun(1);

    return 0;

}

这样的代码就产生了一个从整型数值1到自定义类型Test的隐式转换,当然这里例子没有实际意义。

当自定义类定义了隐式转换操作符的时候,也可能会产生自定义类型到其他类型的隐式转换,这里的其他类型就是隐式转换操作符的时候的类型。例如:

class Test{

    int v_;

public:

    Test(int i) : v_(i){}

    operator int() const{return v_;}

};

 

void fun(int i)

{

    std::cout<<i;

}

 

int main()

{

    fun(Test(1));

    return 0;

}

这样的代码就产生了一个从自定义类型Test到整型数值1的隐式转换,当然这里例子没有实际意义。

在实际编程中,隐式转换会给程序员带来很多困扰,因为是隐式的,所以往往发生在程序员不知情的情况下,更是难以调试。

为了防止这两种方式产生的隐式类型转换,我们可以在有且仅有一个未指定默认值的参数的构造函数前加上explicit关键字修饰,这个关键字的作用是让这个构造函数只能显示的调用,避免发生隐式转换。我们也尽量不去定义隐式转换操作符,除非不会给使用者带来任何困扰和问题。

 

友元函数:有些时候我们或许会希望授权某个外部函数能够访问我们的私有成员,但是其他未被授权的函数不能访问,这个时候就可以用到友元函数了。将希望授权的函数声明为自定义类的友元函数,那么它就能访问自定义类的私有成员了。例如:

class Test{

    int v_;

public:

    explicit Test(int i) : v_(i){}

    friend void fun(const Test&);

};

 

void fun(const Test& test)

{

    std::cout<<test.v_;

}

 

int main()

{

    fun(Test(1));

    return 0;

}

 

模板成员函数:自定义类的成员函数也可以是模板函数,这样类似于定义了一系列相同名字的成员函数。例如:

class Printer{

    std::ostream& o_;

public:

    explicit Printer(std::ostream& o) : o_(o){}

    template<typename T>

    void Print(const T& v)

    {

       o_<<v;

    }

};

 

int main()

{

    Printer printer(std::cout);

    printer.Print(1);

    return 0;

}

 

重载操作符:自定义类可以通过重载操作符来让自己可以通过操作符来完成一定的功能。例如:std::string就重载了+操作符,完成了字符串的拼接功能。

 

以上就是本章的一些概念,教材中通过实现一个简化版的字符串类Str,来对这几个概念分别讲解并指出了一些编码中应该遵守的惯用法和如何避免可能会带来的问题,课堂上将不再赘述。

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 2
    评论
评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值