当前位置:  开发笔记 > 编程语言 > 正文

如何避免大型代码库中的常见错误?

如何解决《如何避免大型代码库中的常见错误?》经验,为你挑选了2个好方法。

有没有办法取消定义chars和wchar_t的字符串和字符串的+ =?

基本上我想避免以下错误:

int age = 27;

std::wstring str = std::wstring(L"User's age is: ");
str += age;

std::string str2 = std::string("User's age is: ");
str2 += age;

上面的代码将ascii字符27添加到字符串而不是数字27.

我显然知道如何解决这个问题,但我的问题是:在这种情况下如何产生编译器错误?

注意:您可以在std :: string和int上覆盖+ =以正确格式化字符串,但这不是我想要做的.我想在这些操作数上完全禁止这个操作符.



1> Klaim..:

您无法停用类的特定功能(此处为std :: basic_string),因为它的界面明显(并且正式)允许该操作.试图使操作员超载只会搞砸.

现在,您可以使用私有继承或组合将std :: basic_string"包装"在另一个类中,然后使用公共接口作为std :: basic_string部分的代理,但只使用您希望可用的函数.

我建议先用typedef替换你的字符串类型:

namespace myapp
{
    typedef std::string String;
    typedef std::wstring UTFString;
}

然后,一旦你的应用程序在用myapp :: String和myapp :: UTFString(那些是示例名称)替换std :: string和std :: wstring之后编译正常,你可以在某处定义包装类:

namespace myapp
{
/** std::basic_string with limited and controlled interface.
    */
    template< class _Elem, class _Traits, class _Ax >
    class limited_string 
    {
    public:
        typedef std::basic_string< _Elem , _Traits, _Ax > _String; // this is for easier writing
        typedef limited_string< _Elem, _Traits, _Ax > _MyType; // this is for easier writing

    private:
        _String m_string; // here the real std::basic_string object that will do all the real work!

    public:

        // constructor proxies... (note that those ones are not complete, it should be exactly the same as the original std::basic_string
        // see some STL docs to get the real interface to rewrite)
        limited_string() : m_string {}
        limited_string( const _MyType& l_string ) : m_string( l_string.m_string ) {}
        limited_string( const _Elem* raw_string ) : m_string( raw_string ) {}
        //... etc...

        // operator proxies...
        _MyType& operator= ( const _MyType& l_string ) 
        {
            m_string = l_string.m_string;
        }
        // etc...
        // but we don't want the operator += with int values so we DON'T WRITE IT!

        // other function proxies...
        size_t size() const { return m_string.size(); } // simply forward the call to the real string!
        // etc...you know what i mean...

        // to work automatically with other STL algorithm and functions we add automatic conversion functions:
        operator const _Elem*() const { return m_string.c_str(); } 

        // etc..        


    };
}

...然后,您只需替换这些行:

// instead of those lines...
    //typedef std::string String; 
    //typedef std::wstring UTFString;

    // use those ones
    typedef limited_string< char, std::char_traits, std::allocator >                String; // like std::string typedef
    typedef limited_string< wchar_t, std::char_traits, std::allocator >       UTFString; // like std::wstring typedef 

...而你的例子会崩溃:

error C2676: binary '+=' : 'myapp::UTFString' does not define this operator or a conversion to a type acceptable to the predefined operator
error C2676: binary '+=' : 'myapp::String' does not define this operator or a conversion to a type acceptable to the predefined operator

这是我编写的完整测试应用程序代码,用于证明(在vc9上编译):

#include 
#include 

namespace myapp
{

    /** std::basic_string with limited and controlled interface.
    */
    template< class _Elem, class _Traits, class _Ax >
    class limited_string 
    {
    public:
        typedef std::basic_string< _Elem , _Traits, _Ax > _String; // this is for easier writing
        typedef limited_string< _Elem, _Traits, _Ax > _MyType; // this is for easier writing

    private:
        _String m_string; // here the real std::basic_string object that will do all the real work!

    public:

        // constructor proxies... (note that those ones are not complete, it should be exactly the same as the original std::basic_string
        // see some STL docs to get the real interface to rewrite)
        limited_string() : m_string {}
        limited_string( const _MyType& l_string ) : m_string( l_string.m_string ) {}
        limited_string( const _Elem* raw_string ) : m_string( raw_string ) {}
        //... etc...

        // operator proxies...
        _MyType& operator= ( const _MyType& l_string ) 
        {
            m_string = l_string.m_string;
        }
        // etc...
        // but we don't want the operator += with int values so we DON'T WRITE IT!

        // other function proxies...
        size_t size() const { return m_string.size(); } // simply forward the call to the real string!
        // etc...you know what i mean...

        // to work automatically with other STL algorithm and functions we add automatic conversion functions:
        operator const _Elem*() const { return m_string.c_str(); } 

        // etc..        


    };

    // instead of those lines...
    //typedef std::string String; 
    //typedef std::wstring UTFString;

    // use those ones
    typedef limited_string< char, std::char_traits, std::allocator >                String; // like std::string typedef
    typedef limited_string< wchar_t, std::char_traits, std::allocator >       UTFString; // like std::wstring typedef 
}

int main()
{
    using namespace myapp;

    int age = 27;

    UTFString str = UTFString(L"User's age is: ");
    str += age; // compilation error!
    std::wcout << str << std::endl;

    String str2 = String("User's age is: ");
    str2 += age; // compilation error!
    std::cout << str2 << std::endl;

    std::cin.ignore();

    return 0;
}

我认为它会干净地解决你的问题,但你必须包装所有的功能.



2> Martin York..:

大多数源代码控制系统允许您在签入期间对代码运行健全性检查.因此,您可以设置测试以执行验证并拒绝签入失败:

例:

测试脚本:

#!/bin/tcsh
# Pass the file to test as the first argument.

echo "#include \
void operator+=(std::string const& , int const&);\
void operator+=(std::string const& , int);"\
| cat - $1 \
| g++ -c -x c++ -  >& /dev/null


echo $status

该脚本伪造了上面两个运算符的添加(实际上没有改变源).即使原始代码编译,这也会导致使用operator + with strings和char失败.

NB:运营商+ =从litb窃取的想法.谁已经删除了他的例子.但信用到期.

推荐阅读
凹凸曼00威威_694
这个屌丝很懒,什么也没留下!
DevBox开发工具箱 | 专业的在线开发工具网站    京公网安备 11010802040832号  |  京ICP备19059560号-6
Copyright © 1998 - 2020 DevBox.CN. All Rights Reserved devBox.cn 开发工具箱 版权所有