我是靠谱客的博主 踏实白昼,最近开发中收集的这篇文章主要介绍c++函数explicit修饰符,觉得挺不错的,现在分享给大家,希望可以做个参考。

概述

本文参考了以下两篇博客:[C++笔记(1)explicit构造函数], [explicit在构造函数的使用 及 详解],只是对自己的学习做一个简要的记录。

问题引入

explicit修饰符的作用是什么,什么时候用?

explicit的主要用法就是放在单参数的构造函数中,防止隐式转换,出现歧义.

因为,只有一个参数的构造函数也定义了一个隐式转换,将该构造函数对应参数的数据类型的数据转换为该类对象。如下面代码所示:

#include <iostream>
#include <cstring>

class MyString{
public:

    MyString( const char* str ){
        int s_len = strlen(str);

        ptr_ = new char[ s_len + 1 ];
        strncpy( ptr_, str, s_len + 1);

    }

    friend std::ostream& operator<<( std::ostream& os, const MyString& s );

private:
    char* ptr_;
    int n_;
};

std::ostream& operator<<( std::ostream& os, const MyString& s ){
    if( os ){
        os << s.ptr_;
    }
    return os;
}

int main(){

    MyString s1( "hello, world!" ); // 单参数构造函数,显示定义
    MyString s2 = "hello, world!"; // 但参数构造函数,隐式转换
    std::cout << s1 << std::endl;
    std::cout << s2 << std::endl;
}

上面这段代码看起来还没有什么问题,但是再看看下面的代码:

#include <iostream>
#include <cstring>

class MyString{
public:
    MyString( int n ) : n_(n) {
        ptr_ = new char[n_];
    }
    MyString( const char* str ){
        int s_len = strlen(str);

        ptr_ = new char[ s_len + 1 ];
        strncpy( ptr_, str, s_len + 1);

    }

    friend std::ostream& operator<<( std::ostream& os, const MyString& s );

private:
    char* ptr_;
    int n_;
};

std::ostream& operator<<( std::ostream& os, const MyString& s ){
    if( os ){
        os << s.ptr_;
    }
    return os;
}

int main(){

    MyString s1( "hello, world!" );
    MyString s2 = "hello, world!";
    std::cout << s1 << std::endl;
    std::cout << s2 << std::endl;

    MyString s3(8); // 单参数构造函数,显示定义
    MyString s4 = 8; // 单参数构造函数,隐式定义
    std::cout << s3 << std::endl;
    std::cout << s4 << std::endl;

}

对于下面的这种写法,容易让人产生误解,这个接口本身的含义是构造含有8个字符的字符串,但是下面的这种写法感觉像是把数字8转换成了一个字符串。

MyString s4 = 8; // 单参数构造函数,隐式定义

问题解决

通过对单参数的构造函数加explicit修饰符,防止隐式转换,出现语义歧义。

#include <iostream>
#include <cstring>

class MyString{
public:
    explicit MyString( int n ) : n_(n) { // 此时,单参数构造函数无法进行隐式转换
        ptr_ = new char[n_];
    }
    MyString( const char* str ){
        int s_len = strlen(str);

        ptr_ = new char[ s_len + 1 ];
        strncpy( ptr_, str, s_len + 1);

    }

    friend std::ostream& operator<<( std::ostream& os, const MyString& s );

private:
    char* ptr_;
    int n_;
};

std::ostream& operator<<( std::ostream& os, const MyString& s ){
    if( os ){
        os << s.ptr_;
    }
    return os;
}

int main(){

    MyString s1( "hello, world!" );
    MyString s2 = "hello, world!";
    std::cout << s1 << std::endl;
    std::cout << s2 << std::endl;

    MyString s3(8);
    MyString s4 = 8;
    std::cout << s3 << std::endl;
    std::cout << s4 << std::endl;

}

转换构造函数的细节问题

想看以下转换构造函数在不进行优化时的具体行为。是否还是要生成临时对象。

#include <iostream>
#include <cstring>

class MyString{
public:
    typedef size_t size_type;

public:

    MyString(){}
    explicit MyString( int n, char ch = 0 ) : n_(n) {
        ptr_ = new char[n_ + 1];
        for( int i = 0; i < n_; ++i ){
            ptr_[i] = ch;
        }
        ptr_[n_] = 0;
    }
    MyString( const char* str ){

        n_ = strlen(str);
        ptr_ = new char[ n_ + 1 ];

        strncpy( ptr_, str, n_ + 1);

        std::cout << "conversion constructor called!" << std::endl;
    }
    MyString( const MyString& rhs ){

        n_ = rhs.size();
        ptr_ = new char[n_ + 1];

        for( int i = 0; i < n_; ++i ){
            ptr_[i] = rhs.ptr_[i];
        }
        ptr_[n_] = 0;

        std::cout << "copy constructor called!" << std::endl;
    }
    MyString& operator=( const MyString& rhs ){

        if( &rhs != this ){

            delete [] ptr_;

            n_ = rhs.size();
            ptr_ = new char[n_ + 1];

            for( int i = 0; i < n_; ++i ){
                ptr_[i] = rhs.ptr_[i];
            }
            ptr_[n_] = 0;

        }
        std::cout << "assignment function called!" << std::endl;
        return *this;
    }

    ~MyString(){
        delete [] ptr_;
        std::cout << "destructor called!" << std::endl;
    }


    size_type size() const { return n_; }

    friend std::ostream& operator<<( std::ostream& os, const MyString& s );

private:
    char* ptr_;
    int n_;
};

std::ostream& operator<<( std::ostream& os, const MyString& s ){
    if( os ){
        os << s.ptr_;
    }
    return os;
}

int main(){

    MyString s2 = "hello, world!";
    std::cout << s2 << std::endl;


}
/*
程序输出:
conversion constructor called!// 转换构造函数生成临时对象
copy constructor called!// 临时对象通过拷贝构造函数生成左值对象
destructor called!//临时对象析构
hello, world!
destructor called!//左值对象析构
*/

最后

以上就是踏实白昼为你收集整理的c++函数explicit修饰符的全部内容,希望文章能够帮你解决c++函数explicit修饰符所遇到的程序开发问题。

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

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

评论列表共有 0 条评论

立即
投稿
返回
顶部