C ++:传递类可变参数函数 [英] C++: Passing classes to vararg function

查看:141
本文介绍了C ++:传递类可变参数函数的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我试图做一个行为像MS的CString类(也就是你将它传递给printf和它的行为就像一个指针,C字符串,而无需额外丑陋的黑魔法,如.c_str())。

I'm trying to make a class that behaves like MS CString (that is, you pass it to printf and it acts just like a pointer to C string, without additional ugly black magic like ".c_str()").

这是第一个实施这一类的,那只是工作,并且未提供任何有用的:

This is very first implementation of this class, that just works and doesn't yet provide anything useful:

#include <cstdlib>
#include <cstring>

class CString
{
protected:
    struct CStringInfo
    {
        size_t Length;
        size_t MaxLength;
    };

public:
    CString()
    {
        Buffer = NULL;

        Assign(NULL);
    }

    CString(const char* chv)
    {
        Buffer = NULL;

        Assign(chv, 0);
    }

    ~CString()
    {
        if(Buffer) delete[] Buffer;
        Buffer = NULL;
    }

    size_t GetLength()
    {
        if(!Buffer) Alloc(1);
        return GetInfo()->Length;
    }

    size_t Resize(size_t size)
    {
        Alloc(size + 1); // + 0x00
        Buffer[size] = 0;
        return size;
    }

    bool Assign(const char* value, size_t size = 0)
    {
        size_t strl = ((size) ? size : strlen(value));

        if(!value || !(strl = strlen(value)))
        {
            if(!Buffer) Alloc(1);
            return false;
        }

        Alloc(strl + 1);
        memcpy(Buffer, value, strl);
        Buffer[strl] = 0;
        return true;
    }

    CString& operator = (const char* what)
    {
        Assign(what);
        return (*this);
    }

    CString& operator = (CString& string)
    {
        Assign(string.Buffer);
        return (*this);
    }

    operator const char* ()
    {
        return Buffer;
    }

protected:
    char* Buffer;

    void Alloc(size_t size)
    {
        if(!size) size = 1;
        char* nb = new char[size + sizeof(CStringInfo)];
        char* nbb = nb + sizeof(CStringInfo);
        size_t cl = size - 1;
        if(Buffer)
        {
            if(cl > GetInfo()->Length) cl = GetInfo()->Length;
            if(cl) memcpy(nbb, Buffer, cl - 1);
            nbb[cl] = 0;
            *(CStringInfo*)(nb) = *(CStringInfo*)(Buffer);
            delete[] (Buffer - sizeof(CStringInfo));
        }

        Buffer = nb;
        GetInfo()->MaxLength = size;
        GetInfo()->Length = cl;
    }

    void Free()
    {
        if(Buffer)
        {
            delete[] (Buffer - sizeof(CStringInfo));
        }
    }

    CStringInfo* GetInfo()
    {
        return (CStringInfo*)(this->Buffer - sizeof(CStringInfo));
    }
};

和code我测试它:

#include <cstdio>
#include "CString.hpp"

CString global_str = "global string!";

int main(int argc, char* argv[])
{
    CString str = "string";
    printf("Test: %s, %s\n", str, global_str);
    return 0;
}

如果我没有在类析构函数,那么我可以将它传递给printf和它的工作就像它应该(为C字符串)。但是,当我加入析构函数,GCC会产生以下错误:

If I don't have a destructor in the class, then I can pass it to printf and it will work just like it should (as a C string). But when I add destructor, GCC produces following error:

error: cannot pass objects of non-trivially-copyable type 'class CString' through '...'

和除海湾合作委员会的事先版本将给予警告+ UD2运code。

And in addition to that prior versions of GCC will give a warning + ud2 opcode.

所以......提问:其实我可以做以下的建设工作在GCC或者有没有什么办法,可能不涉及Ç可变参数,使一些在使用中与上面code

So... Question: can I actually make following construction work in GCC or is there any way, possibly not involving C varargs, to make something identical in use to above code?

推荐答案

您可以用投触发转换操作符:

You can trigger the conversion operator with a cast:

printf("Test: %s, %s\n", static_cast<const char*>(str), 
       static_cast<const char*>(global_str));

不过,我不知道你是否会遇到这种任何问题,避免在C ++中code可变参数可能会是最好的。

However, I don't know if you will run into any problems with this, avoiding varargs in C++ code would probably be the best.

如何使用类型安全的printf ,而不是(来源:维基百科):

How about using the type-safe printf instead (Credit: Wikipedia):

void printf(const char *s)
{
    while (*s) {
        if (*s == '%') {
            if (*(s + 1) == '%') {
                ++s;
            }
            else {
                throw std::runtime_error("invalid format string: missing arguments");
            }
        }
        std::cout << *s++;
    }
}

template<typename T, typename... Args>
void printf(const char *s, T value, Args... args)
{
    while (*s) {
        if (*s == '%') {
            if (*(s + 1) == '%') {
                ++s;
            }
            else {
                std::cout << value;
                printf(s + 1, args...); // call even when *s == 0 to detect extra arguments
                return;
            }
        }
        std::cout << *s++;
    }
    throw std::logic_error("extra arguments provided to printf");
}

我不认为的libstdc ++支持的std :: runtime_error 的std :: logic_error 虽然

这篇关于C ++:传递类可变参数函数的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆