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

来源:互联网 发布:淘宝网的账号不能登录 编辑:程序博客网 时间:2024/06/09 21:28

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

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,来对这几个概念分别讲解并指出了一些编码中应该遵守的惯用法和如何避免可能会带来的问题,课堂上将不再赘述。

原创粉丝点击