64,654
社区成员
发帖
与我相关
我的任务
分享
// std::string 基类
class A : public std::string
{
std::string left(long n)
{
retrun std::string(begin(), begin() +n);
}
}
// 使用
std::string str(abc);
std::string str2 = ( (A*)(&str))->left(2); // 这样可以,但显得丑陋
class stringXX :public std::string
{
public:
using string::basic_string<char, char_traits<char>, allocator<char> >; // 声明OK,但并未继承构造函数
using string::cend;
};
class AA
{
public: AA(int){};
};
class AAX :public AA
{
public:
using AA::AA;
};
int main()
{
AAX aax(1); // ERROR
stringXX xx("dddd"); // ERROR
}
using string::string;
你这个代码是不对的,不对的地方有三个。
一、宏名不是__ARGS__,而是__VA_ARGS__
二、__VA_ARGS__这个只能用在宏定义中,也就是#define……中
三、即使这样能转发,从原理上说string的构造函数也不可能取出参数,也无法知道参数的数量。先说参数数量比较好理解,c语言的printf知道吧,有没有想过为什么需要第一个参数——格式控制字符串,例如"%d%s%f",实际上格式控制字符串告诉printf函数,后面变参的部分有3个参数,分别是整形(int),字符串,单精度浮点(float)。所以没有一个参数来说明变参部分具体有多少个参数,谁都不知道。接着就是函数要处理变参数,就必须要使用几个宏,分别是 va_start,va_list,va_arg,va_end。这几个宏是通过格式化控制字符串的给出的类型决定要读取多少个字节的内容并转换为什么类型的
综上,这种转发虽然看上去合理,但是从原理上不行。直接用构造函数继承就可以了
#include <string>
using namespace std;
class X :public string
{
public:
using string::string;
};
int main()
{
X x("123456");
return 0;
}
class stringXX :public std::string
{
public:
//stringXX(...) :std::string(__ARGS__){}; // ERROR, 不可转发
stringXX(const std::string& r) :std::string(r){};
};
int main()
{
std::string strORG("abcde");
OutputDebugStringA(strORG.c_str());
strORG += "ddd";
stringXX strXX(std::string("abcde"));
OutputDebugStringA(strXX.c_str());
strXX += "ddd";
}
与其这样搞,那跟这样有什么不同?
void format(string& s, int n)
{
// 进行处理
}
int main()
{
std::string str("000");
format(str, 123456789);
// ……
}
用起来的复杂度是一样的,性能也很是一样的。最简洁的办法还是用继承,然后直接使用派生类。[/quote]
template<class _Elem, class _Traits, class _Ax>
class basic_stringX
{
public:
typedef basic_string<_Elem, _Traits,_Ax > value_type;
public:
value_type& v;
basic_stringX(value_type& v_) :v(v_){};
public:
long format(const _Elem* fmt, ...)
{
v.clear();
const BOOL bW =std::tr1::is_same<wchar_t, _Elem>::value;
long sz=0;
if(bW) sz =_vscwprintf((const wchar_t*)fmt, args); // 能运行,release下无消耗,不过丑陋
else sz =_vscprintf((const char*)fmt, args);
if (sz >0)
{
va_list args;
va_start( args, fmt );
v.resize(sz +1);
if(bW) _vsnwprintf_s((wchar_t*)&v[0], (sz +1) *sizeof(v[0]), sz +1, (const wchar_t*)fmt, args ); // 能运行,release下无消耗,不过丑陋
else _vsnprintf_s((char*)&v[0], (sz +1) *sizeof(v[0]), sz +1, (const char*)fmt, args );
v.resize(sz);
va_end ( args );
}
return sz;
};
};
typedef basic_stringX<char, char_traits<char>, allocator<char> > stringX;
typedef basic_stringX<wchar_t, char_traits<wchar_t>, allocator<wchar_t> > wstringX;
int main()
{
std::string str("000");
stringX(str).format("%d", 123456789);
printf(str.c_str());
std::wstring strW(L"0000");
wstringX(strW).format(L"%d", 123456789);
wprintf(strW.c_str());
printf("getchar()");
getchar();
}
首先这个“使用”本身就有问题,只添加一个函数还没什么,但是如果有数据成员你的这个使用方法就不行了,是访问不到数据成员的。
所以这种拓展不可行,一个办法像楼上上说的改string类的代码,第二个就是将要用有left函数的string类的地方改用类A。
附:
你的left函数【【【就是】】】如题目所给的实现的吗?就是截取字符串的前多少个字符?
如果是的话用string类的substr函数就行了:
[/quote]
void format(string& s, int n)
{
// 进行处理
}
int main()
{
std::string str("000");
format(str, 123456789);
// ……
}
用起来的复杂度是一样的,性能也很是一样的。最简洁的办法还是用继承,然后直接使用派生类。